當前位置:
首頁 > 知識 > C++—const volatile mutable的用法

C++—const volatile mutable的用法


const volatile mutable的用法

_______________________________________________

相信const大家對他並不陌生,可能大家在日常的編寫代碼當中就會時常用到const,但是剩下的兩個關鍵字不知道我們有

沒有使用過volatile和mutable兩個關鍵字其實不算特別常用,但是我們一定要知道這個關鍵字有什麼用,應該怎麼用.首

先const的基本操作我曾經寫過一篇博客:const的基本使用

現在我要說一個const操作裡面比較騷的一些做法,

舉個例子我們以前寫過的一個類,我們會使用operator[]來返回一個reference的指向,這個一般情況我們都會寫一個

const的也會寫一個非const的opeartor[].這是我們最常見的一個代碼:


  1. T& operator[](int position)

  2. {

  3. return xxx[position];

  4. }

  5. const T& operator[](int position) const

  6. {

  7. return xxx[position];

  8. }

這是我們平時寫的初級的代碼,但是現在當我們要寫一個TextBlock內的opeartor[]不單只返回一個referencr了

,也可能執行邊界檢查,日誌訪問信息,還有什麼數據完善性檢驗等等一大堆繁瑣的代碼,這個時候當你實現

operator[] const和operator[]() const,的時候兩份代碼大部分都一樣,這裡伴隨的是代碼重複,編譯時間變長,

維護代碼膨脹等等頭疼的問題. 當然啦,你可以讓上述那些繁瑣的函數全部封裝的別的函數中,然後分別在

operator[]()和operator[]()const當中調用但是你還說重複了一些代碼比如兩次return語句,函數調用.真正該做

的是實現operator[]的機能一次並使用它兩次。也就是你只需要寫一個函數,令另外一個調用這個,這促使我們將

常量性轉移. 接下來 見證奇蹟我們來看看下面這個代碼是怎麼實現的上述的操作的:


  1. class TextBlock

  2. {

  3. public:

  4. ...

  5. constchar& operator[](std::size_t position) const

  6. {

  7. ...

  8. ...

  9. ...

  10. return text[position];

  11. }

  12. constchar& operator[](std::size_t position)

  13. {

  14. returnconst_cast<char&>(static_cast<const TextBlock&>(*this)[position]);

  15. }

  16. };

來仔細看這個操作;return const_cast<char&>(static_cast<const TextBlock&>(*this)[position]);

首先把*this強制轉換為const TextBlock,再然後調用const的operator[],最後再把const的operator[]的返回值的

const常量性取消,然後返回一個非const的值. 這裡的調用實在是太妙了,我們可以思考一下,好好想想這裡的深意.

但是會有人說,為什麼不用const operator[]調用operator[]呢,這樣強制兩個都可以行的通啊.這樣想是錯的!

令const版本調用調用no-const版本以避免重複並不是你該做的事情. 記住const所修飾函數的承諾就是我絕對不會修

改你,no-const函數可沒有這種承諾,所以你讓一個const函數去調用一個no-const函數是不現實的. over

其實const有很多可以玩的屬性,只要我們想到就可以去實現,這裡就說這麼一個就ok. 接下來我們來瞧瞧另外兩個

關鍵字.

mutable

———————————————————————————————————————

其實呢,這個關鍵字的作用就是mutalbe的中文意思是「可變的,易變的」,跟constant是反義詞就是我們上邊說的

const在C++中,mutable也是為了突破const的限制而設置的。被mutable修飾的變數(mutable只能由於修飾類的

非靜態數據成員),將永遠處於可變的狀態,即使在一個const函數中。

實際運用起來也非常容易,就是你想改變的元素被const修飾了,你就往它前面加上mutable那麼你就無敵了..

我就舉一個最簡單的例子,我定一個AA類,我在AA類中定義一個MT()函數,該函數屬性為const屬性,再然後我

想在MT()函數中添加該函數執行多少次時,程序編不過去了. 因為const修飾的函數裡面的所有值都不能修改.

代碼舉例:

[cpp] view plain copy


  1. class AA

  2. {

  3. public:

  4. void MT() const

  5. {

  6. i++;

  7. cout << "hehe";

  8. cout << "執行了" << i << "次該程序";

  9. }

  10. private:

  11. int i = 0;

  12. };

但是這樣編不過去啊,因為MT()函數為const函數,所以不能修改i的值,但是如果我在這裡使用mutable關鍵字的


話,現在我們把i加上mutable關鍵字,這樣它永遠就是一個可變的了. 來我們加上去試一試,

  1. class AA

  2. {

  3. public:

  4. void MT() const

  5. {

  6. i++;

  7. cout << "hehe" << " ";

  8. cout << "執行了" << i << "次該程序" << endl;;

  9. }

  10. private:

  11. mutableint i = 0;

  12. };

  13. int main()

  14. {

  15. AA a;

  16. a.MT();

  17. a.MT();

  18. a.MT();

  19. a.MT();

  20. return 0;

  21. }

運行結果:

C++—const volatile mutable的用法

這就是mutable的最簡單的一個應用,以後可以根據需求來使用~


volatile

______________________________________________________________________

一個定義為volatile的變數是說這變數可能會被意想不到地改變,這樣,編譯器就不會去假設這個變數的值了。精確地

說就是,優化器在用到這個變數時必須每次都小心地重新讀取這個變數的值,而不是使用保存在寄存器里的備份。下

面是volatile變數的幾個例子:

1.並行設備的硬體寄存器(如:狀態寄存器

2.一個中斷服務子程序中會訪問到的非自動變數(Non-automatic variables)

3.多線程應用中被幾個任務共享的變數

看下面例題:


  1. int square(volatileint *ptr)

  2. {

  3. return *ptr * *ptr;

  4. }

這個程序有什麼問題嗎? 如果我們不去關心volatile關鍵字的話,那麼這個程序你怎麼看都會覺得沒多大問題.但是這裡

面問題大這ne, 首先參數聲明為volatile就是表明*ptr可能會隨時改變.上述代碼運行時,編譯器可能產生這樣的代碼:

[cpp] view plain copy

  1. int square(volatileint *ptr)

  2. {

  3. int a,b;

  4. a = *ptr;

  5. b = *ptr;

  6. return a * b;

  7. }

因為你的*ptr是隨時都可以意想不到的變化,所以有可能a*b的時候,a b的值不相同. 這樣你就得到一個錯誤的結果

改正後的程序:

[cpp] view plain copy

  1. int square(volatileint *ptr)

  2. {

  3. int a;

  4. a = *ptr;

  5. return a * a;

  6. }

第二個問題,看如下代碼:


  1. #include<iostream>

  2. #include<Windows.h>

  3. #include<assert.h>

  4. usingnamespace std;

  5. int main()

  6. {

  7. constint a = 2;

  8. int *p = const_cast<int*>(&a);

  9. *p = 3;

  10. cout << a << endl;

  11. system("pause");

  12. return 0;

  13. }

我們有理由的認為在內存當中a的值被修改為3,但是結果呢? 我們來看一看

C++—const volatile mutable的用法

這不科學啊?? 我們再打開監視窗口看一下a的值.

C++—const volatile mutable的用法

我們都知道監視窗口看到的都是從內存當中拿到的,但是為什麼內存當中為3,列印出來就是2呢? 我來解釋一下.

C++編譯器具有優化功能,當你定一個const的常量的時候,系統覺得它不會被改變了,於是做一個優化把該常量存到寄

存器當中,下次訪問的過程更快速一點. 所以當顯示窗口讀取數據的時候,他會直接去寄存器當中讀取數據.而不是去

內存,所以導致我們明明該掉了a的值,卻列印不出來.

這個時候該我們的volatile出馬了,往i前面加一個volatile之後就會解決這個問題,來看結果:

C++—const volatile mutable的用法

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 青峰科技 的精彩文章:

騰訊雲DevOps流水線的應用與實踐
前方高能提示:SDCC 2017之區塊鏈技術實戰線上峰會開播倒計時
html 使用 gka 加速 createjs 動畫開發及圖片優化
Chrome 搜索 User-Agent Switcher 排行第一的插件竟是木馬
三分鐘讀懂TT貓分散式、微服務和集群之路

TAG:青峰科技 |