C++const 關鍵字小結
const 是constant的縮寫,本意是不變的,不易改變的意思。
const 在C++中是用來修飾內置類型變量,自定義對象,成員函數,返回值,函數參數。
short conclusion
// for variable
const int a = 8;
int *p = (int *)&a;
*p =7; // wrong, it's unpredictable
// for pointer, 左定值,右定向
int a = 8;
const int *p = &a;
*p = 7; // wrong
int * const p2 = &a;
int b = 10;
p2 = &b; // wrong
// for func param
class A {};
void func(const A *a){} // equal to void func(const A& a){}, improve performance for copy constructor comparing to void func(A a)
void func(A * const a){} // equal to void func(A& a){}
// for class method, indicate 'the method can't modify the instance data', (mutable修飾的變量除外)
// 不能調用非const成員函數
class B{
private:
int count;
public:
int GetCount() const {
count ++; // wrong
return count;
}
}
// for return value, no practical value
一、const修飾普通類型的變量。
如下:
const int a = 7;
int b = a; //it's right
a = 8; // it's wrong,
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; //it’s right
int b = 7;
p = &b; //it’s wrong
對於const指針p其指向的內存地址不能夠被改變,但其內容可以改變。簡稱,右定向。因為const位於*號的右邊。
對於C:
則是A和B的合並,
int a = 8;
const int * const p = &a;
這時,const p的指向的內容和指向的內存地址都已固定,不可改變。
const修飾指針Conclusion
對於A,B,C三種情況,根據const位於*號的位置不同,我總結三句話便於記憶的話,
左定值,右定向,const修飾不變量。
三、const in function參數傳遞
對於const修飾函數參數可以分為三種情況。
值傳遞的const修飾傳遞
A:值傳遞的const修飾傳遞,一般這種情況不需要const修飾,因為函數會自動產生臨時變量復制實參值。
#include<iostream>
using namespace std;
void Cpf(const int a)
{
cout<<a;
// ++a; it's wrong, a can't is changed
}
int main(void)
{
Cpf(8);
system("pause");
return 0;
}
const參數為指針
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 is 9
system("pause");
return 0;
}
self definded type, const reference
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; //it's wrong
++_ct; //it's right
}
private:
int _cm;
mutable int _ct;
};
int main(void)
{
Test t(8,7);
return 0;
}
這里我們在Kf()const中通過++_ct;修改_ct的值,但是通過++_cm修改_cm則會報錯。因為++_cm沒有用mutable修飾。
轉載:
C++ const用法 盡可能使用const https://www.cnblogs.com/xudong-bupt/p/3509567.html
C++const 關鍵字小結 https://www.cnblogs.com/Forever-Kenlen-Ja/p/3776991.html