標籤:int 可變 函數 ios ret 不可 tab ola oid
C++const 關鍵字小結
const 是constant的縮寫,本意是不變的,不易改變的意思。
const 在C++中是用來修飾內建類型變數,自訂對象,成員函數,傳回值,函數參數。
一、const修飾普通類型的變數。
如下:
1 const int a = 7; 2 3 int b = a; //it‘s right4 5 a = 8; // it‘s wrong,
a被定義為一個常量,並且可以將a賦值給b,但是不能給a再次賦值。對一個常量賦值是違法的事情,因為a被編譯器認為是一個常量,其值不允許修改。
接著看如下的操作:
1 2 3 #include<iostream> 4 5 using namespace std; 6 7 int main(void) 8 9 {10 11 const int a = 7;12 13 int *p = (int*)&a;14 15 *p = 8;16 17 cout<<a;18 19 system("pause");20 21 return 0;22 23 }
對於const變數a,我們取變數的地址並轉換賦值給 指向int的指標,然後利用*p = 8;重新對變數a地址內的值賦值,然後輸出查看a的值。
從下面的調試視窗看到a的值被改變為8,但是輸出的結果仍然是7。
從結果中我們可以看到,編譯器然後認為a的值為一開始定義的7,所以對const a的操作就會產生上面的情況。所以千萬不要輕易對const變數設法賦值,這會產生意想不到的行為。
如果不想讓編譯器察覺到上面到對const的操作,我們可以在const前面加上volatile關鍵字
Volatile關鍵字跟const對應相反,是易變的,容易改變的意思。所以不會被編譯器最佳化,編譯器也就不會改變對a變數的操作。
1 #include<iostream> 2 3 using namespace std; 4 5 int main(void) 6 7 { 8 9 volatile const int a = 7;10 11 int *p = (int*)&a;12 13 *p = 8;14 15 cout<<a;16 17 system("pause");18 19 return 0;20 21 }
輸出結果如我們期望的是8
二、const 修飾指標變數。
const 修飾指標變數有以下三種情況。
A:const 修飾指標指向的內容,則內容為不可變數。
B:const 修飾指標,則指標為不可變數。
C:const 修飾指標和指標指向的內容,則指標和指標指向的內容都為不可變數。
對於A:
1 const int *p = 8;
//則指標指向的內容8不可改變。簡稱左定值,因為const位於*號的左邊。
對於B:
1 int a = 8;2 3 int* const p = &a;4 5 *p = 9; //it’s right6 7 int b = 7;8 9 p = &b; //it’s wrong
//對於const指標p其指向的記憶體位址不能夠被改變,但其內容可以改變。簡稱,右定向。因為const位於*號的右邊。
對於C:
則是A和B的合并,
1 int a = 8;2 3 const int * const p = &a;4 5
//這時,const p的指向的內容和指向的記憶體位址都已固定,不可改變。
對於A,B,C三種情況,根據const位於*號的位置不同,我總結三句話便於記憶的話,
“左定值,右定向,const修飾不變數”。
三、const參數傳遞和函數傳回值。
對於const修飾函數參數可以分為三種情況。
A:值傳遞的const修飾傳遞,一般這種情況不需要const修飾,因為函數會自動產生臨時變數複製實參值。
1 #include<iostream> 2 3 using namespace std; 4 5 void Cpf(const int a) 6 7 { 8 9 cout<<a;10 11 // ++a; it‘s wrong, a can‘t is changed12 13 }14 15 int main(void)16 17 {18 19 Cpf(8);20 21 system("pause");22 23 return 0;24 25 }
B:當const參數為指標時,可以防止指標被意外篡改。
1 #include<iostream> 2 3 using namespace std; 4 5 void Cpf(int *const a) 6 7 { 8 9 cout<<*a<<" ";10 11 *a = 9;12 13 }14 15 int main(void)16 17 {18 19 int a = 8;20 21 Cpf(&a);22 23 cout<<a; // a is 924 25 system("pause");26 27 return 0;28 29 }
C:自訂類型的參數傳遞,需要臨時對象複製參數,對於臨時對象的構造,需要調用建構函式,比較浪費時間,因此我們採取const外加引用傳遞的方法。
並且對於一般的int ,double等內建類型,我們不採用引用的傳遞方式。
1 #include<iostream> 2 3 using namespace std; 4 5 class Test 6 7 { 8 9 public:10 11 Test(){}12 13 Test(int _m):_cm(_m){}14 15 int get_cm()const16 17 {18 19 return _cm;20 21 }22 23 private:24 25 int _cm;26 27 };28 29 30 31 void Cmf(const Test& _tt)32 33 {34 35 cout<<_tt.get_cm();36 37 }38 39 int main(void)40 41 {42 43 Test t(8);44 45 Cmf(t);46 47 system("pause");48 49 return 0;50 51 }
//結果輸出 8
對於const修飾函數的傳回值
Const修飾傳回值分三種情況。
A:const修飾內建類型的傳回值,修飾與不修飾傳回值作用一樣。
1 #include<iostream> 2 3 using namespace std; 4 5 const int Cmf() 6 7 { 8 9 return 1;10 11 }12 13 int Cpf()14 15 {16 17 return 0;18 19 }20 21 int main(void)22 23 {24 25 int _m = Cmf();26 27 int _n = Cpf();28 29 30 31 cout<<_m<<" "<<_n;32 33 system("pause");34 35 return 0;36 37 }
B:const 修飾自訂類型的作為傳回值,此時返回的值不能作為左值使用,既不能被賦值,也不能被修改。
C: const 修飾返回的指標或者引用,是否返回一個指向const的指標,取決於我們想讓使用者幹什麼。
四、const修飾類成員函數.
const 修飾類成員函數,其目的是防止成員函數修改被調用對象的值,如果我們不想修改一個調用對象的值,所有的成員函數都應當聲明為const成員函數。注意:const關鍵字不能與static關鍵字同時使用,因為static關鍵字修飾靜態成員函數,靜態成員函數不含有this指標,即不能執行個體化,const成員函數必須具體到某一執行個體。
下面的get_cm()const;函數用到了const成員函數
1 #include<iostream> 2 3 using namespace std; 4 5 class Test 6 7 { 8 9 public:10 11 Test(){}12 13 Test(int _m):_cm(_m){}14 15 int get_cm()const16 17 {18 19 return _cm;20 21 }22 23 private:24 25 int _cm;26 27 };28 29 30 31 void Cmf(const Test& _tt)32 33 {34 35 cout<<_tt.get_cm();36 37 }38 39 int main(void)40 41 {42 43 Test t(8);44 45 Cmf(t);46 47 system("pause");48 49 return 0;50 51 }
如果get_cm()去掉const修飾,則Cmf傳遞的const _tt即使沒有改變對象的值,編譯器也認為函數會改變對象的值,所以我們盡量按照要求將所有的不需要改變對象內容的函數都作為const成員函數。
如果有個成員函數想修改對象中的某一個成員怎麼辦?這時我們可以使用mutable關鍵字修飾這個成員,mutable的意思也是易變的,容易改變的意思,被mutable關鍵字修飾的成員可以處於不斷變化中,如下面的例子。
1 #include<iostream> 2 using namespace std; 3 class Test 4 { 5 public: 6 Test(int _m,int _t):_cm(_m),_ct(_t){} 7 void Kf()const 8 { 9 ++_cm; //it‘s wrong10 ++_ct; //it‘s right11 }12 private:13 int _cm;14 mutable int _ct;15 };16 17 int main(void)18 {19 Test t(8,7);20 return 0;21 }
這裡我們在Kf()const中通過++_ct;修改_ct的值,但是通過++_cm修改_cm則會報錯。因為++_cm沒有用mutable修飾。
C++ const用法小結 (歡迎大家拍磚)