C++的const關鍵字標記了一個變量(或者函數)的常量屬性,程序員通過const關鍵字告訴編譯器:這個變量是不可修改的常量,任何企圖對其進行修改的操作不要通過編譯。
const關鍵字的使用比較容易混淆,參考《Effective C++》現總結如下:
1:通過const關鍵字替代替代宏定義
(item 2:prefer consts enums,inlines to #defines)
在C++編程環境下,儘量通過const和enum替代#define
比如:
#define ASPECT_RATION 1.653
ASPECT_RATION 在編譯之前就已經通過預處理替換成數字1.653,編譯的時候,將會有多份1.653在可執行程序當中。另外1.653也不會進入符號表,會給debug造成困難。
在類定義裏面,使用靜態常量,有可能編譯器不支持,此時,可以使用枚舉實現常量的定義
class A
{
public:
//static const int a=100;//此語句編譯器有可能不支持類常量聲明,必須在類外定義
//通過g++實驗,是可以編譯通過的
enum {size=100};
int array[a];
}
另外,宏定義的函數,有可能會導致未預期的錯誤
//a,b取較大值
#define MAX(a,b) ( (a) > (b) ? (a) : (b))
int a=3,b=6;
int c=MAX(a,b++);
上述調用,會使得b++調用2遍,可以使用內聯的函數模板實現同樣的功能
template<typename T>
inline MAX(T a, T b)
{
return a > b ? a : b;
}
2:const關鍵字使用
const char *p;
//p是一個指向常量字符的指針,p的指向可以修改,p所指內容不得修改
p++; //OK
*p='F'; //Error
char * const p;
//p是一個指向字符的常量指針,p的指向不得修改,p所指內容可以修改
p++; //Error
*p='F'; //OK
//以上內容比較容易混淆,一個區分的方法是從右邊往左邊讀
//const char *p; p is a pointer which pointed to a type of const char;
//char * const p; p is a const pointer whoes value can't be changed.
const char * const p;
//p是一個常量指針,指向一個常量型字符,p的指向和p指向的值都不得修改
3:const成員函數
類的定義當中,可以將某些成員函數聲明爲const類型,const成員函數不得修改類的成員變量。
對於一個const的實例變量,只能調用const函數(因爲非const成員函數有可能修改成員變量,無法保證實例的const屬性)
對於一個非const的實例變量,既可以調用const函數,也可以調用非const函數
class A
{
public:
A():a(100)
{
x=new char(100);
strcpy(x,"talk is cheap,show me the code."
}
int get_a_const() const
{
//a=10; error
//*x="F"; OK,此處是const函數爭議的地方,的確沒有修改指針變量,但是修改了指針指向的內容
return a;
}
int get_a_nonconst()
{
//a=10; OK
return a;
}
private:
int a;
char *x;
};
const A x;
x.get_a_const(); //OK
x.get_a_nonconst(); //Error
A y;
y.get_a_const(); //OK,非const類變量,可以調用const成員函數和非const成員函數
y.get_a_nonconst(); //OK
4:結語
我們應該在能夠使用const變量的地方,儘量寫上const,可以讓編譯器檢查出語法錯誤,使得代碼更安全,出錯機率更低
如果能在編譯時報錯,爲什麼要等到運行時呢?
Use const as whenever possible