之前總感覺C/C++中有const 限定的變量是個非常頭痛的問題,一會兒可以變,一會兒不可以變,一會兒把const賦給nonconst,一會兒又把nonconst賦給const,頭都被它搞大了。今天剛好把《C++ primer》中的相關部分又讀了一遍,所以就把相關的內容寫出來總結一下啦!
首先,我們可以想想為什麼要設計const變量這種東西,不過就是想有個常量嘛!所以對const類型變量進行操作的核心原則就是不能改變該變量的值,其他操作的話,const還是不const影響其實不大。
然後我們可以想到的是,既然在程序執行過程中,不能改變const變量的值,那麼我們在對該變量進行定義的時候就必須對它進行初始化。對於像int,double這樣的普通變量來說,初始化一般有如下三種方式:
const int i = fun(); //利用函數返回值初始化 const int j = 42;//字面值 const int k = i;//其他變量這裡我們值得注意的是第一種和第三種的賦值方式。我們可能會有這樣的疑問,萬一i的類型或者fun函數的返回值的類型不是const int類型的怎麼辦呢?這時候我們就可以想想前面提到過的那個原則了。由於賦值只是將一個變量的值賦給另外一個,從此之後兩者就基本上每什麼關系了。所以不會對原來const類型變量的值產生影響。所以賦值操作完全可以無視等號兩邊的變量類型。
普通類型變量的const相關問題還是非常簡單的,下面就再來講講reference(引用)和pointer(指針)的相關問題。我們都知道引用類型也是必須要初始化的,並且在初始化之後不能再將該引用指向其他的變量。這點與指針有很大的不同。所以我們完全可以認為引用本身就是const的,因為它自己的值是不能改變的。現在我們有下面四個賦值語句:
int j const int i; const int &r1 = i; int &r2 = j; const int &r3 = j; int &r4 = i;很明顯,前面兩條的賦值語句是不會有任何問題的,因為等號兩變的變量類型是完全一樣的。事實上我們完全可以將一個const類型的引用指向一個nonconst類型的變量,就像第三個等式一樣。因為我們只要保證變量的值不能通過r3進行改變就可以了,至於實際上j的值變不變是不在r3的管轄范圍之內的,或者說即使變了也無所謂,j本來就是nonconst類型的。但是,如果反過來將一個noncosnt類型的引用指向一個const類型的變量就不行了,因為你此時可以同過r4去改變一個const類型變量的值。
最後我們來看看指針類型的const問題。如下所示,對於一個指針變量來說,const一般會存在在兩個位置:
int a; const int *p = &a; int *const q = &a;
對於第一種類型,我們可以和對引用的操作做一個類比,其實是差不多的。那麼對於第二中聲明怎麼解讀呢?正如《C++ primer》中所說的那樣,我們可以從變量開始從右往左讀,q前面首先是const。所以q自己的值是不變的。再往做是 int*,因此q就是一個指向int類型的const變量。因為q本身是const的,所以它的值不能改變,始終指向變量a。
總之,說到底還是開頭說過的那句話,const類型變量的核心原則是它的值不能改變。只要以此進行判斷,不管是references to const ,pointers to const,consts pointer,還是const賦值給nonconst,nonconst賦值給const,我想都不是問題啦!