標籤:strong 就是 調用 span size div font 代碼 prime
定義
const關鍵字的作用是對變數的類型加以限定。被const修飾的變數值不可改變(初始化後不可以再被賦值),例如:
const int num1 = 1;num1 = 1; //錯誤
const表示變數是不可寫的,但是這並不影響變數的可讀性:
const int num1 = 1;int num2 = num1; //正確,可以使用常量對象進行拷貝初始化
const引用
使用const修飾的引用稱為對常量的引用,實際上是將引用綁定到一個常量對象上。
const int num1 = 1;const int &r1 = num1; //正確,常量引用r1綁定到常量對象num1上
需要注意的是,非常量引用不能綁定到常量對象上。這是因為可以通過非常量引用修改其綁定的對象,所以非常量引用只能綁定到非常量對象上。
const int num1 = 1;int &r2 = num1; //錯誤,不能將非常量引用r2綁定到常量對象num1上
雖然非常量引用不能綁定到常量對象上,但是常量引用卻可以綁定到非常量對象上。
int num2 = 1;const int &r1 = num2; //正確,常量引用r1綁定到非常量對象num2上
關於引用(常量、非常量)和對象(常量、非常量)的綁定關係,我們可以這樣理解,引用只是一個別名,我們使用引用的目的是通過引用修改其綁定的對象,我們不會去修改常量引用綁定的對象,所以常量引用可以綁定到常量對象上,也可以綁定到非常量對象上;相反,非常量引用只能綁定到非常量對象上。
既然常量引用不會去修改其綁定的對象,那麼直接將常量引用綁定到字面值或者一般運算式上也是可以的:
const int &r1 = 1; //正確,常量引用r1綁定的值是0
const指標
使用const修飾的指標稱為常量指標,常量指標必須初始化,而且一旦初始化完成,它的值(存放在指標中的地址)就不能再改變了。
int num3 = 1;int *const p1 = &num3; //p1將一直指向num3
需要注意的是,指標指標本身是一個常量並不意味著不能通過指標修改其所指的對象的值。
int num3 = 1;int *const p1 = &num3; //p1將一直指向num3*p1 = 2; //此句結束後num3的值變為2
那麼,如何使得指標所指對象的值不能修改呢?只要使用const修飾對象即可,此時指標的定義語句前面也要加上const:
const int num4 = 1;const int *const p2 = &num4; //p2將一直指向num4*p2 = 2; //錯誤,不能修改num4的值num4 = 2; //錯誤,不能修改num4的值
上面代碼中p2的定義語句中出現了兩個const,這兩個const的含義是不同的,第一個const表示指標指向的對象的值是不可修改的,第二個const表示指標本身(指標也是對象,它的值就是它儲存的地址值)是不可修改的。這兩個const的不同含義就是下面要講的頂層const和底層const。
頂層const和底層const
頂層const表示指標本身是一個常量,即指標一直指向一個對象。
底層const表示指標所指的對象是一個常量,即指標所指的對象是不可修改的。
int num4 = 1;int *const p2 = &num4; //頂層constconst int *p3 = &num4; //底層constconst int *const p4 = &num4; //既是頂層const,又是底層const
引用可以看作是底層const,和引用一樣,不能將一個非底層const指標指向常量對象:
const int num5 = 1;int *p5 = &num5; //錯誤,不能將非底層const指標p5指向常量對象num5int *const p6 = &num5; //錯誤,不能將非底層const指標p6指向常量對象num5
const成員函數
在C++類的定義中,可以在成員函數的參數列表後加上const,const的作用是修改隱式this指標的類型。
何為隱式this指標?我們通過對象調用成員函數時,成員函數如何知道是哪一個對象對其的調用呢?實際上,成員函數會包含一個名為this的額外的隱式參數,當我們調用一個成員函數時,成員函數會用請求該函數的對象地址初始化this。我們來看下面的代碼:
class Person{ private: int height = 170; int weight = 60; public: int getHeight() //普通成員函數 { return height; //相當於return this.height; } int getWeight() const //const成員函數 { return weight; //相當於return this.weight; }};Person person1;int h1 = person1.getHeight(); //正確,此時會將person1的地址隱式賦給getHeight函數的隱式參數thisint w1 = person1.getWeight(); //正確const Person person2;int h2 = person2.getHeight(); //錯誤,不能在一個常量對象上調用一個普通的成員函數int w2 = person2.getWeight(); //正確
對象一旦建立,this就會一直指向這個對象,所以其實this是一個常量指標(頂層const)。
this預設情況下是一個頂層const(Person *const this),下面的代碼示範了person1和person2調用getHeight函數時的隱式初始化語句。
//下面用p1表示person1的指標,p2表示person2的指標Person *const this = Person *p1; //person1調用getHeight函數,正確Person *const this = const Person *p2; //person2調用getHeight函數,錯誤
常量對象person2調用普通成員函數getHeight時,隱式初始化語句企圖將一個常量對象賦給一個非常量對象(底層),所以會引發錯誤。在這種情況下,如果this指標是底層const,我們的初始化語句就沒問題,const成員函數的作用就在此。下面的代碼示範了person1和person2調用getWeight函數時的隱式初始化語句。
//下面用p1表示person1的指標,p2表示person2的指標const Person *const this = Person *p1; //person1調用getWeight函數,正確const Person *const this = const Person *p2; //person2調用getWeight函數,正確
總結
- 被const修飾的變數值不可寫,但是可讀;
- 無論是引用還是指標,非常量可以向常量轉換,但反之不可,即常量引用/指標可以指向非常量對象,而非常量引用/指標不可以指向常量對象;
- 頂層const是指指標本身不可變,底層const是指指標指向的對象不可變;
- const成員函數中的const可以修改隱式this指標的類型。
參考文獻
《C++ Primer》第5版
C++ const關鍵字