C++ const 关键字小结
const 是 constant 的縮寫,本意是不變的,不易改變的意思。在 C++ 中是用來修飾內置類型變量,自定義對象,成員函數,返回值,函數參數。
C++ const 允許指定一個語義約束,編譯器會強制實施這個約束,允許程序員告訴編譯器某值是保持不變的。如果在編程中確實有某個值保持不變,就應該明確使用const,這樣可以獲得編譯器的幫助。
一、const修飾普通類型的變量
const int a = 7; int b = a; // 正確 a = 8; // 錯誤,不能改變a 被定義為一個常量,并且可以將 a 賦值給 b,但是不能給 a 再次賦值。對一個常量賦值是違法的事情,因為 a 被編譯器認為是一個常量,其值不允許修改。
接著看如下的操作:
實例
#include<iostream>using namespace std;int main(void) {const int a = 7;int *p = (int*)&a;*p = 8;cout<<a;system("pause");return 0; }對于 const 變量 a,我們取變量的地址并轉換賦值給 指向 int 的指針,然后利用 *p = 8; 重新對變量 a 地址內的值賦值,然后輸出查看 a 的值。
從下面的調試窗口看到 a 的值被改變為 8,但是輸出的結果仍然是 7。
從結果中我們可以看到,編譯器然后認為 a 的值為一開始定義的 7,所以對 const a 的操作就會產生上面的情況。所以千萬不要輕易對 const 變量設法賦值,這會產生意想不到的行為。
如果不想讓編譯器察覺到上面到對 const 的操作,我們可以在 const 前面加上 volatile 關鍵字。
Volatile 關鍵字跟 const 對應相反,是易變的,容易改變的意思。所以不會被編譯器優化,編譯器也就不會改變對 a 變量的操作。
實例
#include<iostream>using namespace std;int main(void) {volatile const int a = 7;int *p = (int*)&a;*p = 8;cout<<a;system("pause");return 0; }輸出結果如我們期望的是 8。
二、const 修飾指針變量。
const 修飾指針變量有以下三種情況。
- A: const 修飾指針指向的內容,則內容為不可變量。
- B: const 修飾指針,則指針為不可變量。
- C: const 修飾指針和指針指向的內容,則指針和指針指向的內容都為不可變量。
對于 A:
const int *p = 8;則指針指向的內容 8 不可改變。簡稱左定值,因為 const 位于 * 號的左邊。
對于 B:
int a = 8; int* const p = &a; *p = 9; // 正確 int b = 7; p = &b; // 錯誤對于 const 指針 p 其指向的內存地址不能夠被改變,但其內容可以改變。簡稱,右定向。因為 const 位于 * 號的右邊。
對于 C:?則是 A 和 B的合并
int a = 8; const int * const p = &a;這時,const p 的指向的內容和指向的內存地址都已固定,不可改變。
對于 A,B,C 三種情況,根據 const 位于 * 號的位置不同,我總結三句話便于記憶的話:"左定值,右定向,const修飾不變量"。
三、const參數傳遞和函數返回值。
對于 const 修飾函數參數可以分為三種情況。
A:值傳遞的 const 修飾傳遞,一般這種情況不需要 const 修飾,因為函數會自動產生臨時變量復制實參值。
實例
#include<iostream>using namespace std;void Cpf(const int a) {cout<<a;// ++a; 是錯誤的,a 不能被改變 }int main(void){Cpf(8);system("pause");return 0; }B:當 const 參數為指針時,可以防止指針被意外篡改。
實例
#include<iostream>using namespace std;void Cpf(int *const a) {cout<<*a<<" ";*a = 9; }int main(void) {int a = 8;Cpf(&a);cout<<a; // a 為 9system("pause");return 0; }C:自定義類型的參數傳遞,需要臨時對象復制參數,對于臨時對象的構造,需要調用構造函數,比較浪費時間,因此我們采取 const 外加引用傳遞的方法。
并且對于一般的 int、double 等內置類型,我們不采用引用的傳遞方式。
實例
#include<iostream>using namespace std;class Test { public:Test(){}Test(int _m):_cm(_m){}int get_cm()const{return _cm;}private:int _cm; };void Cmf(const Test& _tt) {cout<<_tt.get_cm(); }int main(void) {Test t(8);Cmf(t);system("pause");return 0; }結果輸出?8。
對于 const 修飾函數的返回值。
Const 修飾返回值分三種情況。
A:const 修飾內置類型的返回值,修飾與不修飾返回值作用一樣。
實例
#include<iostream>using namespace std;const int Cmf() {return 1; }int Cpf() {return 0; }int main(void) {int _m = Cmf();int _n = Cpf();cout<<_m<<" "<<_n;system("pause");return 0; }B: const 修飾自定義類型的作為返回值,此時返回的值不能作為左值使用,既不能被賦值,也不能被修改。
C: const 修飾返回的指針或者引用,是否返回一個指向 const 的指針,取決于我們想讓用戶干什么。
四、const修飾類成員函數
const 修飾類成員函數,其目的是防止成員函數修改被調用對象的值,如果我們不想修改一個調用對象的值,所有的成員函數都應當聲明為 const 成員函數。
注意:const 關鍵字不能與 static 關鍵字同時使用,因為 static 關鍵字修飾靜態成員函數,靜態成員函數不含有 this 指針,即不能實例化,const 成員函數必須具體到某一實例。
下面的 get_cm()const; 函數用到了 const 成員函數:
實例
#include<iostream>using namespace std;class Test { public:Test(){}Test(int _m):_cm(_m){}int get_cm()const{return _cm;}private:int _cm; };void Cmf(const Test& _tt) {cout<<_tt.get_cm(); }int main(void) {Test t(8);Cmf(t);system("pause");return 0; }如果 get_cm() 去掉 const 修飾,則 Cmf 傳遞的 const _tt 即使沒有改變對象的值,編譯器也認為函數會改變對象的值,所以我們盡量按照要求將所有的不需要改變對象內容的函數都作為 const 成員函數。
如果有個成員函數想修改對象中的某一個成員怎么辦?這時我們可以使用 mutable 關鍵字修飾這個成員,mutable 的意思也是易變的,容易改變的意思,被 mutable 關鍵字修飾的成員可以處于不斷變化中,如下面的例子。
實例
#include<iostream> using namespace std; class Test { public:Test(int _m,int _t):_cm(_m),_ct(_t){}void Kf()const{++_cm; // 錯誤++_ct; // 正確} private:int _cm;mutable int _ct; };int main(void) {Test t(8,7);return 0; }這里我們在 Kf()const 中通過 ++_ct; 修改 _ct 的值,但是通過 ++_cm 修改 _cm 則會報錯。因為 ++_cm 沒有用 mutable 修飾。
原文地址:https://www.cnblogs.com/Forever-Kenlen-Ja/p/3776991.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的C++ const 关键字小结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么激活windows10专业版 激活W
- 下一篇: C++构造函数总结