C++中mutable與volatile的深入理解
前言
C++中修飾數(shù)據(jù)可變的關(guān)鍵字有三個:const、volatile和mutable。const比較好理解,表示其修飾的內(nèi)容不可改變(至少編譯期不可改變),而volatile和mutable恰好相反,指示數(shù)據(jù)總是可變的。mutable和volatile均可以和const搭配使用,但兩者在使用上有比較大差別。
下面話不多說了,來一起看看詳細的介紹吧
mutable
mutable只能作用在類成員上,指示其數(shù)據(jù)總是可變的。不能和const 同時修飾一個成員,但能配合使用:const修飾的方法中,mutable修飾的成員數(shù)據(jù)可以發(fā)生改變,除此之外不應(yīng)該對類/對象帶來副作用。
考慮一個mutable的使用場景:呼叫系統(tǒng)中存有司機(Driver)的信息,為了保護司機的隱私,司機對外展現(xiàn)的聯(lián)系號碼每隔五分鐘從空閑號碼池更新一次。根據(jù)需求,Driver類的實現(xiàn)如下偽代碼:
class Driver { private: ... // real phone number string phone; // display phone number mutable string displayPhone; public: string getDisplayPhone() const { if (needUpdate()) { lock.lock(); if (needUpdate()) { updateDisplayPhone(); // displayPhone在這里被改變 } lock.unlock(); } return displayPhone; } };
在上述代碼中,const方法中不允許對常規(guī)成員進行變動,但mutable成員不受此限制。對Driver類來說,其固有屬性(姓名、年齡、真實手機號等)未發(fā)生改變,符合const修飾。mutable讓一些隨時可變的展示屬性能發(fā)生改變,達到了靈活編程的目的。
volatile
volatile用于修飾成員或變量,指示其修飾對象可能隨時變化,編譯器不要對所修飾變量進行優(yōu)化(緩存),每次取值應(yīng)該直接讀取內(nèi)存。由于volatile的變化來自運行期,其可以與const一起使用。兩者一起使用可能讓人費解,如果考慮場景就容易許多:CPU和GPU通過映射公用內(nèi)存中的同一塊,GPU可能隨時往共享內(nèi)存中寫數(shù)據(jù)。對CPU上的程序來說,const修飾變量一直是右值,所以編譯通過。但其變量內(nèi)存中的值在運行期間可能隨時在改變,volatile修飾是正確做法。
在多線程環(huán)境下,volatile可用作內(nèi)存同步手段。例如多線程爆破密碼:
volatile bool found = false; void run(string target) { while (!found) { // 計算字典口令的哈希 if (target == hash) { found = true; break; } } }
在volatile的修飾下,每次循環(huán)都會檢查內(nèi)存中的值,達到同步的效果。
需要注意的是,volatile的值可能隨時會變,期間會導(dǎo)致非預(yù)期的結(jié)果。例如下面的例子求平方和:
double square(volatile double a, volatile double b) { return (a + b) * (a + b); }
a和b都是隨時可變的,所以上述代碼中的第一個a + b可能和第二個不同,導(dǎo)致出現(xiàn)非預(yù)期的結(jié)果。這種情況下,正確做法是將值賦予常規(guī)變量,然后再相乘:
double square(volatile double a, volatile double b) { double c = a + b; return c * c; }
一般說來,volatile用在如下的幾個地方:
1. 中斷服務(wù)程序中修改的供其它程序檢測的變量需要加volatile;
2. 多任務(wù)環(huán)境下各任務(wù)間共享的標(biāo)志應(yīng)該加volatile;
3. 存儲器映射的硬件寄存器通常也要加volatile說明,因為每次對它的讀寫都可能有不同意義;
總結(jié)
mutable只能用與類變量,不能與const同時使用;在const修飾的方法中,mutable變量數(shù)值可以發(fā)生改變;
volatile只是運行期變量的值隨時可能改變,這種改變即可能來自其他線程,也可能來自外部系統(tǒng)。
好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對我們的支持。
參考
https://en.cppreference.com/w/cpp/language/cv
您可能感興趣的文章
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言中對數(shù)函數(shù)的表達式 c語言中對數(shù)怎么表達
- 04-02c語言沒有round函數(shù) round c語言
- 04-02C語言中怎么打出三角函數(shù) c語言中怎么打出三角函數(shù)的值
- 01-10深入理解C++中常見的關(guān)鍵字含義
- 01-10使用C++實現(xiàn)全排列算法的方法詳解
- 01-10深入Main函數(shù)中的參數(shù)argc,argv的使用詳解
- 01-10APUE筆記之:進程環(huán)境詳解
- 01-10c++中inline的用法分析
- 01-10如何尋找數(shù)組中的第二大數(shù)


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機閱讀
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-11ajax實現(xiàn)頁面的局部加載
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10delphi制作wav文件的方法
- 01-10C#中split用法實例總結(jié)
- 04-02jquery與jsp,用jquery
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改