1. 程式人生 > >C++ const用法小結 (歡迎大家拍磚)

C++ const用法小結 (歡迎大家拍磚)

固定 ant oid 幹什麽 pause 參數傳遞 clas 自定義類型 期望

C++const 關鍵字小結

constconstant的縮寫,本意是不變的,不易改變的意思。

const 在C++中是用來修飾內置類型變量,自定義對象,成員函數,返回值,函數參數

一、const修飾普通類型的變量。

如下:

1 const int  a = 7; 
2 
3 int  b = a; //it‘s right
4 
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 right
6 
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 changed
12 
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 9
24 
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()const
16 
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()const
16 
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 wrong
10         ++_ct; //it‘s right
11     }
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用法小結 (歡迎大家拍磚)