const修飾的值并不是常量,而是隻讀的變量。其值在編譯時不能被使用,因為編譯器在編譯時不知道其存儲的内容。
C++ 裡 const 變量一般預設 static 連接配接方式
也就是其它 .cpp 檔案看不到,是以用 extern 聲明也沒用
可将 const 變量的聲明放在 .h 檔案裡,需要使用此常量的 .cpp 都 #include 它
編譯器通常不為普通const隻讀變量配置設定存儲空間,而是将它們儲存在符号表中,這使得Tam它成為一個編譯期間的值,沒有了存儲和讀記憶體的操作,使它的效率很高。
#define M 3 //宏常量
const int N = 5; //此時未将N 放入記憶體
......
int i = N; //此時為N 配置設定記憶體,之後不再配置設定
int I = M; //預編譯期間進行宏替換,配置設定記憶體
int j = N; //沒有記憶體配置設定
int J = M; //再次進行宏替換,再次配置設定記憶體
const定義的隻讀變量從彙編角度上看,隻是給出了對應的記憶體位址,而不是像 #define一樣,給出的是立即數。是以,const定義的隻讀變量在程式運作過程中隻有一份copy,因為他是全局的隻讀變量,放在靜态區。#define 宏實在預編譯階段進行替換,const修飾的隻讀變量是在編譯時确定其值。
?
下面的代碼在存為C檔案在VC6.0編譯器下編譯是錯誤的!為什麼?
#include<stdio.h>
void main()
{
const int bufsize = 10 ;
char buf[bufsize] = {'a','b','c'};//error C2057:expected constant expression
//error C2466: cannot allocate an array of constant size 0
printf ("%S",buf);
}
在編譯時,編譯器并不知道const的值,它隻是一個“運作時常量”。不是放在符号表裡的。(編譯原裡的知識這裡就不多講了!)
然而把上面的代碼改成CPP檔案在VC6.0編譯器下編譯是通過的。
通常,C++編譯器不為const建立存儲空間,而是把它儲存在“符号表”裡,即“編譯時常量”。預設情況下,C++中的const是内部連接配接的,也就是說,const僅在const被定義過
?
的檔案裡才是可見的。(是以,不用擔心名字沖突)當定義一個const時,必須賦一個值給它,除非用extern做出了清楚的說明。當用extern說明了const時,編譯器會強制為const
?
配置設定空間,而不是儲存在符号表中。
const修飾的隻讀變量必須在定義的同時初始化。
用如下方法可以修改const常量,但是如果将const int i=0;放到main函數之外,作為全局變量,則施行的時候會報錯。
#include<stdio.h>
main()
{
const int i=0;
int *p=&i;
*p=3;
printf("%d",i);
}
類中的常量:
在類中,const資料成員隻在某個對象生存期内是常量,而對于整個類而言确實可變的,因為類可以建立多個對象,不同的對象其const資料成員的值可以不同。
不能在類聲明中初始化const資料成員,以下用法錯誤,因為類的對象還未被建立時,編譯器不知道SIZE的值為多少:
class A
{
const int SIZE = 100;
int array[SIZE];
};
const資料成員的初始化隻能在類構造函數的初始化中進行,例如:
class A
{
A(int size);//構造函數
const int SIZE;
};
A::A(int size):SIZE(size)
{
}
A a(100);//對象a的size值為100
A b(200);//對象b的size值為200
要建立在整個類中都恒定的常量,可用枚舉常量來實作。但枚舉常量是整數,不能表示浮點數
class A
{
enum {SIZE1 = 100,SIZE2 = 200};
int array1[SIZE1];
int array2[SIZE2];
}
------------------
用const提高函數健壯性
1、const修飾函數參數
如果參數作輸出用,不管是什麼資料類型,也不管是采用指針傳遞還是引用傳遞,都不能加const,否則該參數将失去輸出功能。
如果參數作為輸入:
值傳遞:形參變動不會影響實參,是以無需保護。不需要加const修飾。無需将void Func1(int x)寫成void Func1(const int x),也無需将void Func2(A a)寫成void Func2(const A a),A為使用者自定義的資料類型。
引用傳遞:對于非内部資料類型的參數而言,像void Func2(A a)這樣聲明的函數效率較低,因為函數體内将産生A類型的臨時對象用于複制參數a,而臨時對象的構造、複制、析構過程都耗費時間。為了提高效率,可以将函數聲明改為void Func2(A &a),引用傳遞不産生臨時對象。但可能改變參數a,是以可以改為void Func2(const A &a) ,但内部資料類型就不需要如此修改,因為int等類型不存在構造析構的過程,值傳遞和引用傳遞的效率相當。
指針傳遞:加const修飾可以防止意外改動該指針。
void stringcopy(char * strdestination , const char strsource); //輸出參數不可加const
用const修飾函數的傳回值
如果給“指針傳遞”方式的函數傳回值加const修飾,那麼函數傳回值的内容不可以被修改,而且隻能被賦給加const修飾的同類型指針:
const char *getstring(void);
char *str = getstring();//錯誤
const char *str = getstring();//正确
如果函數傳回采用“值傳遞”,由于函數會把傳回值複制到外部臨時存儲單元,加const無作用:
不要把int getint(void)寫成const int getint(void)
不要把A getA(void)寫成const A getA (void)
-----------------------------------------------------
const修飾一般變量:
int const i = 2;或 const int i = 2;
修飾數組
int const a[5] = {1,2,3,4,5};
const int a[5] = {1,2,3,4,5};
修飾指針
const int *p;//p可變,p指向的對象不可變 常量指針
int const *p;//p可變,p指向的對象不可變 常量指針
int *const p;//p不可變,p指向的對象可變 指針常量
const int *const p;//指針p和p指向的對象都不可變。
修飾函數參數
修飾函數的傳回值