什麼是const限定符?
Const限定符是我們通常所說的常量限定符,被const修飾的對象具有常量性質,只能讀,不能寫。
為什麼使用const限定符?
用const變量取代“魔數”,代碼更容易理解和維護。例如:以const常變量作為數組的界;const常變量作為switch的條件標號。
C++“最小特權原則”的體現,防止不應該被修改的數據被篡改。例如:很多指針(或迭代器)是邊讀邊移動,而不是邊寫邊移動;很多函數參數是只讀不寫的,使用const限定符不僅可以限制參數被修改,還可以擴大函數可以接受參數的范圍(可以接受const對象作為參數)。
如何使用?const限定符
1、 變量:const 類型 變量名 例如: const int ia = 5;
2、 引用:const 類型 &引用名 例如:const int &ib = ia;
3、 對象:const 類名 對象名
4、 指針:const 類型 * 指針名 (常量指針); 類型 * const 指針名 (指針常量)
5、 數組: const 類型 數組名[Arr_Max]
6、 成員函數: 類名::函數名(形參表) const
PS: 上述幾種情況中,除 指針常量 和 const修飾成員函數外,其他幾種情況的 const 和 類型或者類名(類是一種自定義的類型)的位置可以互換, 比如: const int ia = 5; 與 int const ia = 5; 等同。 建議堅持使用一種風格。
const 限定符幾種用法詳解:
1、 指針
使用指針時涉及到兩個對象:該指針本身和指針指向的對象。根據這兩個對象是否使用const修飾,將會產生以下四種情況:
指向非常量對象的非常量指針 int *ptr;
指向非常量對象的常量指針 int *const ptr1;
指向常量對象的非常量指針 const int *ptr2;
指向常量對象的常量指針 int const *const ptr3;
從右向左解讀聲明:
Ptr1 is a const pointer to int. ptr1 是一個const指針,指向int對象。
Ptr2 is a pointer to const int. ptr2是一個指針,指向const int 對象。
Ptr3 is a const pointer to const int. ptr3是一個const指針,指向const int 對象。
如果指針本身被修飾為常量,則該指針在定義時就應該初始化,且之後都不能變更指向的對象(即不能給指針賦值),但是可以通過解引用修改指向對象的值。
例如:
int i = 10, j = 20;
int *const ia = &i; // 定義時必須初始化
*ia = 100; //正確,可以修改指向變量的值
ia = &j; //錯誤,不允許給const修飾的指針賦值(即使是賦同樣的值)
ia = &i; //錯誤,不允許給const修飾的指針賦值(即使是賦同樣的值)
如果指針指向的對象被修飾為常量,則不能在對指針進行解引用之後修改對象的值,但可以變更指向的對象。
例如:
int i = 10, j = 20;
const int *ia = &i;
*ia = 100; // 錯誤,不允許通過指針修改指向對象的值
ia = &j; // 正確, 指針本身未被const修飾,可以變更指向對象
PS: 試圖通過ia 修改指向變量的值是不被允許的,但並不是說明變量的值不能被修改,我們依然可以通過其他方式修改變量的值,比如直接賦值i = 100。變量的值能不能修改取決於該變量本身。 const修飾指針指向的變量,只代表從該指針的角度來看,這個變量具有const特性,不能通過該指針來修改。也完全可能通過另一個指針來修改,比如: int *ib = &i; *ib = 100 ;
如果指針指向的對象本身具體const特性,則被指向對象的值不允許被修改,包括直接修改或者間接修改(通過指針或者引用修改)。 因此,C++語言強制要求指向const對象的指針也必須具有const特性,否則會出現編譯錯誤(C++ primer 中文第四版)。 這意味著,只有指向常量對象的指針才能指向一個const變量。
例如:
const int i = 10;
int *ia = &i ; //編譯錯誤
const int *ib = &i; //正確
int *const ic = &i; //編譯錯誤
const int *const id = &i; //正確
2、 引用
一個變量的引用即一個變量的別名,引用本身不能再次賦值讓一個引用成為另一個變量的別名。因此,相對於指針,const在修飾引用變量的時候就只需考慮能否通過引用變量來修改綁定變量的值。即只存在兩種引用:const變量的引用 和 非const變量的引用。在其他特性方面,引用和指針一致。
例如:
int i = 10;
const int j = 20;
const int &ra = i; //正確, 表示不能通過ra去修改i的值
int &rb = j; //編譯錯誤,只有const變量的引用才能與const對象綁定
const int &rc = j; //正確
int &const rc = i; //語法錯誤,不同於指針,引用不能這樣定義
PS:在程序加載的時候,系統將內存劃分為5個區域:堆區、棧區、全局區(靜態區)、文字常量區和程序代碼區。對於const修飾的變量,系統沒有劃定專門的區域來保護其中的數據不被修改。也就是說,使用常變量的方式對數據進行保護是通過編譯器作語法限制來實現的。我們依然可以繞過編譯器的限制去修改被const限定為“常量”的區域。例如:C語音中通過指針間接修改const變量的值,C++中借助volatile關鍵字修改const變量的值。 但是C++標准中,對於修改const變量屬於”未定義行為”,其實際結果取決於各種編譯器的實現。因此,不建議修改去const變量的值(這不廢話嘛,如果要修改,定義為const干什麼)。
..............未完待續