const、volatile、mutable关键字
const關鍵字
變量宏方面:
const 修飾變量:常量非指針類型,非指針常量類型并沒有什么區別。
const修飾指針:常量指針:是指針不過指向的是常量可以進行p++操作不能進行*p操作;指針常量:是常量,不過有一個指向它地址的指針,可以進行*p操作,不可以進行p++操作。
用常量代替宏的作用,讓代碼更加易于調試。
函數方面:
常量函數參數,可以簡化代碼和允許常量傳入函數,因為變量可以賦值給常量,但是常量不能賦值給變量。
函數常量返回值,避免返回值間相互賦值,改變返回值。
類對象方面:
常量對象,常量引用,說明常量和引用是不可以改變的。
常量數據成員,才構造函數初始化列表中給出,保護數據作用,數據不能改變。
常量成員函數,是函數不能修改類數據成員的(如果有mutable修飾的數據成員還是可以修改的)。
volatile關鍵字
volatile的本意是“易變的”,volatile關鍵字是一種類型修飾符,用它聲明的類型變量表示可以被某些編譯器未知的因素更改,比如操作系統、硬件或者其它線程等。遇到這個關鍵字聲明的變量,編譯器對訪問該變量的代碼就不再進行優化,從而可以提供對特殊地址的穩定訪問。
當要求使用volatile?聲明的變量的值的時候,系統總是重新從它所在的內存讀取數據,即使它前面的指令剛剛從該處讀取過數據。而且讀取的數據立刻被寄存。例如:
volatile int i=10;
int a = i;
。。。//其他代碼,并未明確告訴編譯器,對i進行過操作
int b = i;
volatile?指出?i是隨時可能發生變化的,每次使用它的時候必須從i的地址中讀取,因而編譯器生成的匯編代碼會重新從i的地址讀取數據放在b中。而優化做法是,由于編譯器發現兩次從i讀數據的代碼之間的代碼沒有對i進行過操作,它會自動把上次讀的數據放在b中。而不是重新從i里面讀(如果是用volatile修飾了那么就會從i中重新讀取變量)。這樣以來,如果i是一個寄存器變量或者表示一個端口數據就容易出錯,所以說volatile可以保證對特殊地址的穩定訪問。
mutable關鍵字
mutalbe的中文意思是“可變的,易變的”,跟constant(既C++中的const)是反義詞。在C++中,mutable也是為了突破const的限制而設置的。被mutable修飾的變量(mutable只能由于修飾類的非靜態數據成員),將永遠處于可變的狀態,即使在一個const函數中。
我們知道,假如類的成員函數不會改變對象的狀態,那么這個成員函數一般會聲明為const。但是,有些時候,我們需要在const的函數里面修改一些跟類狀態無關的數據成員,那么這個數據成員就應該被mutalbe來修飾。下面是一個小例子:
class ClxTest
{
public:
void Output() const;
};
?
void ClxTest::Output() const
{
cout << "Output for test!" << endl;
}
?
void OutputTest(const ClxTest& lx)
{
lx.Output();
}
類ClxTest的成員函數Output是用來輸出的,不會修改類的狀態,所以被聲明為const。
函數OutputTest也是用來輸出的,里面調用了對象lx的Output輸出方法,為了防止在函數中調用成員函數修改任何成員變量,所以參數也被const修飾。
假如現在,我們要增添一個功能:計算每個對象的輸出次數。假如用來計數的變量是普通的變量的話,那么在const成員函數Output里面是不能修改該變量的值的;而該變量跟對象的狀態無關,所以應該為了修改該變量而去掉Output的const屬性。這個時候,就該我們的mutable出場了,只要用mutalbe來修飾這個變量,所有問題就迎刃而解了。下面是修改過的代碼:
class ClxTest
{
public:
ClxTest();
~ClxTest();
?
void Output() const;
int GetOutputTimes() const;
?
private:
mutable?int m_iTimes;
};
?
ClxTest::ClxTest()
{
m_iTimes = 0;
}
?
ClxTest::~ClxTest()
{}
?
void ClxTest::Output() const
{
cout << "Output for test!" << endl;
m_iTimes++;
}
?
int ClxTest::GetOutputTimes() const
{
return m_iTimes;
}
?
void OutputTest(const ClxTest& lx)
{
cout << lx.GetOutputTimes() << endl;
lx.Output();
cout << lx.GetOutputTimes() << endl;
}
計數器m_iTimes被mutable修飾,那么它就可以突破const的限制,在被const修飾的函數里面也能被修改。
總結
以上是生活随笔為你收集整理的const、volatile、mutable关键字的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: bzoj1025题解
- 下一篇: Lucene.Net如何实现搜索结果分类