const對普通變量進(jìn)行修飾进副,以表該變量在以后的使用中不被修改叛本。
初始化
/*
*因?qū)ο笠坏﹦?chuàng)建后其值便不能被修改恬吕,所以必須進(jìn)行初始化
*根據(jù)初始化的值給定的表達(dá)式归露,初始化時機(jī)會再編譯時或運行時確定
*當(dāng)編譯確定時想诅,會在調(diào)用其值的地方編譯時便用其值進(jìn)行替換
*(類似于define文本替換,但是define不會作類型檢查)
*/
const int i = 12; //編譯時初始化
const int j = get_size(); //運行時初始化
等價寫法:
int const i = 12;
int const j = get_size();
const 對象作用域
默認(rèn)僅在當(dāng)前文本文件有效
需要在多個文件中生效時,需要在其聲明和定義處用extern進(jìn)行修飾
xxx.cc
extern const int i = 123;
xxx.h
extern const int i;
const 引用及指針
引用 [1]
當(dāng)我們使用引用時一般都期望改變其值, 但是對于const對象本身是不被允許.
修改的,因此對于想把const對象綁定到引用時需要進(jìn)行const修飾, 以表該引用不會改變其值.
引用的類型必須與其引用對象的類型一致 [2], 但是在初始化常量引用時只要表達(dá)式的結(jié)果能轉(zhuǎn)換成引用的類型即可坟冲。例如
double dval = 3.14;
const int &ri = dval;
原因是編譯器做了如下替換:
const int temp = dval;
const int &ri = temp;
// temp 是編譯器臨時創(chuàng)建的用于暫存表達(dá)式求值結(jié)果的臨時變量。
// 另const引用可以綁定在非const變量上
int i = 3;
const int &k_ri = i;
i = 5; //此時k_ri == 5溃蔫;
指針及頂層const和底層const
指針本身是個變量健提,那其也可被const修飾,用于表明該指針的值不會被改變伟叛。
由于指針指向的亦是一個變量私痹,那么該變量也存在const修飾的可能性,即一個指針變量可能存在雙層const. 所謂低層const即用于修飾指針本身不會被改變统刮,頂層const用于修飾指針指向的變量不會被改變紊遵。
int i = 1, b= 2;
const int *p = &i; //底層const, *p解引用的值無法被改變, 但是p可以指向別的變量
*p = 4; //不合法
p = &b; //合法
int *const p2 = &i; //頂層const, p2無法指向其它變量侥蒙,但是*p解引用的值可以改變.
*p2 = 1; //合法
p2 = &b; //不合法
注意:
進(jìn)行對象拷貝時暗膜,對象必須有相同的底層const, 而頂層const則不影響.
const 在類中的使用
class Foo {
public:
...
int get_i() { ++z_; return i_;}
int get_z() { return z_; };
...
private:
int i_; //隨意...
int z_; //計數(shù)get_i() 被調(diào)用的次數(shù);
}
//對于Foo這樣的類鞭衩,如果某一天我們頭腦發(fā)熱想要聲明一個常量,并調(diào)用相關(guān)成員学搜,如下
const Foo k_var;
k_var.get_i(); //調(diào)用出錯
k_var.get_z(); //調(diào)用出錯
//對于成員函數(shù)的調(diào)用會提示報錯,因為這些函數(shù)的調(diào)用可能會改變內(nèi)部成員變量的值论衍,
//這與你的期望不匹配瑞佩。因此我們必須聲明一個可被常量調(diào)用的版本, 通常如下,
class Foo {
public:
...
int get_i() { ++z_; return i_;}
int get_i() const { ++z_; return i_;} //常量版本
int get_z() { return z_; };
int get_z() const { return z_; }; //常量版本
...
}
k_var.get_i(); //調(diào)用出錯
k_var.get_z(); //正確
//此時對get_z()的調(diào)用是正確的坯台,但是get_i()仍然是錯誤的钉凌,
//因為它試圖在const成員函數(shù)里面改變成員變量的值z_,
//成員函數(shù)一旦被const修飾,通常意味著this指針的形態(tài)在其內(nèi)部是const *this(便于理解)捂人,
//那么++this->z_這樣的操作肯定是不合法的。
//但是對于z_這樣我們希望無論在常量或非常量中都希望能夠改變的值矢沿,我們可以在聲明前加mutable修飾滥搭,表明是個可變的數(shù)據(jù)
class Foo {
public:
...
int get_i() { ++z_; return i_;}
int get_i() const { ++z_; return i_;} //常量版本
int get_z() { return z_; };
int get_z() const { return z_; }; //常量版本
...
private:
int i_; //隨意...
mutable int z_; //計數(shù)get_i() 被調(diào)用的次數(shù);
}
k_var.get_i(); //正確