1.為什麼要用const const本質上其實不僅僅是對變數的一個限定符,更是對程式員的一個限定符,它提醒了程式員,通過const限定的變數的值是不應該被更改的,並且當編譯器得知變數或者表達式的求值結果是恆定的時候,編譯器也可以在編譯期大展拳腳,為我們做出一些編譯期優化,進而提高我們的程式在運行時的 ...
1.為什麼要用const
const本質上其實不僅僅是對變數的一個限定符,更是對程式員的一個限定符,它提醒了程式員,通過const限定的變數的值是不應該被更改的,並且當編譯器得知變數或者表達式的求值結果是恆定的時候,編譯器也可以在編譯期大展拳腳,為我們做出一些編譯期優化,進而提高我們的程式在運行時的性能(例如編譯器會在編譯時直接將字面值常量插入我們的代碼段)。
2.const的基本用法
- 用來進行基本類型變數的聲明
/*const變數在初始化的時候必須賦予值*/ int z;//正確: 常規變數初始化可不給明確值 const int x = 5; //正確: 以字面值常量5來進行初始化 //const int y; 錯誤:const變數的聲明必須進行初始化 const int y = z; //正確:const型的變數可以被非const型變數進行初始化 /*const變數不允許被修改*/ //x = 3; y = 3 錯誤:不允許對const型變數進行修改
- 用來對指針或者引用這種複合類型進行聲明
其實在c++primer中,對於const修飾指針的這種情況有一個非常好的說明:/*關於常量指針與指針常量*/ int value = 5; const int c_value = 5; const int* p = &value; //正確:pointer to const 可以被常規變數地址初始化 const int* p1 = &c_value; //正確:pointer to const 可以被const變數地址初始化 //*p = 3, *p1 = 3 錯誤:無法通過pointer to const來改變所指向變數的值 int* const p2 = &value; //正確: 聲明一個const pointer *p2 = 3; //正確: 可以通過const pointer來更改它所指向的值 //p2 = &c_value; 錯誤: const pointer所指向的地址無法被修改 /*引用類型與指針類型類似*/ const int& cref = value; //正確: 可通過常規變數初始化 const int& cref_1 = c_value;//正確: 可以通過const變數初始化 //cref = 4 錯誤: 不可通過reference to const改變原變數的值
指針本身是一個對象,它又可以指向另一個對象。因此,指針本身是不是常量以及指針所指的是不是一個常量就是兩個相互獨立的問題。用名詞頂層const表示指針本身是一個常量,而用名詞底層const表示指針所指的對象是一個常量。
- 用於面向對象程式相關設計時
class base { private: int m_data; mutable int m_data_1; public: void print() const {cout << "Const version!\n";} //聲明一個const型的函數 void print() {cout << "Non const version\n";} //同名非const型函數,可以與上面函數構成重載 // void set(int x) const {m_data = x;} 錯誤:不能在const成員函數中改變m_data的值 void set(int x) const {m_data_1 = x;} //正確:可以對mutable變數進行修改 } //並且當實例化一個const base對象時,其只能調用其常成員函數。
3.總結
在初始化時,const型變數往往沒有特別嚴格的要求,無論用const變數,字面值常量還是常規變數來進行初始化都是合法的操作,但是一旦初始化完成後,const變數便開始拒絕修改操作,並且我們可以將這個性質推廣到類的成員函數之上,類的常成員函數不可以對內部成員變數進行修改(大部分情況下),而至於通過類實例化的常對象也只能調用我們的常成員函數。總的來說,const可以讓我們的程式更加安全,通過這種編譯時的檢查,我們可以確保一些我們不想變更的值保持其原本的樣子。