聊聊C++的mutable和volatile
C++中修飾數(shù)據(jù)可變的關(guān)鍵字有三個(gè):const、volatile和mutable。const比較好理解,表示其修飾的內(nèi)容不可改變(至少編譯期不可改變),而volatile和mutable恰好相反,指示數(shù)據(jù)總是可變的。mutable和volatile均可以和const搭配使用,但兩者在使用上有比較大差別。
mutable
mutable只能作用在類成員上,指示其數(shù)據(jù)總是可變的。不能和const 同時(shí)修飾一個(gè)成員,但能配合使用:const修飾的方法中,mutable修飾的成員數(shù)據(jù)可以發(fā)生改變,除此之外不應(yīng)該對(duì)類/對(duì)象帶來(lái)副作用。
考慮一個(gè)mutable的使用場(chǎng)景:呼叫系統(tǒng)中存有司機(jī)(Driver)的信息,為了保護(hù)司機(jī)的隱私,司機(jī)對(duì)外展現(xiàn)的聯(lián)系號(hào)碼每隔五分鐘從空閑號(hào)碼池更新一次。根據(jù)需求,Driver類的實(shí)現(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方法中不允許對(duì)常規(guī)成員進(jìn)行變動(dòng),但mutable成員不受此限制。對(duì)Driver類來(lái)說(shuō),其固有屬性(姓名、年齡、真實(shí)手機(jī)號(hào)等)未發(fā)生改變,符合const修飾。mutable讓一些隨時(shí)可變的展示屬性能發(fā)生改變,達(dá)到了靈活編程的目的。
volatile
volatile用于修飾成員或變量,指示其修飾對(duì)象可能隨時(shí)變化,編譯器不要對(duì)所修飾變量進(jìn)行優(yōu)化(緩存),每次取值應(yīng)該直接讀取內(nèi)存。由于volatile的變化來(lái)自運(yùn)行期,其可以與const一起使用。兩者一起使用可能讓人費(fèi)解,如果考慮場(chǎng)景就容易許多:CPU和GPU通過(guò)映射公用內(nèi)存中的同一塊,GPU可能隨時(shí)往共享內(nèi)存中寫(xiě)數(shù)據(jù)。對(duì)CPU上的程序來(lái)說(shuō),const修飾變量一直是右值,所以編譯通過(guò)。但其變量?jī)?nèi)存中的值在運(yùn)行期間可能隨時(shí)在改變,volatile修飾是正確做法。
在多線程環(huán)境下,volatile可用作內(nèi)存同步手段。例如多線程爆破密碼:
volatile bool found = false;
void run(string target) {
while (!found) {
// 計(jì)算字典口令的哈希
if (target == hash) {
found = true;
break;
}
}
}
在volatile的修飾下,每次循環(huán)都會(huì)檢查內(nèi)存中的值,達(dá)到同步的效果。
需要注意的是,volatile的值可能隨時(shí)會(huì)變,期間會(huì)導(dǎo)致非預(yù)期的結(jié)果。例如下面的例子求平方和:
double square(volatile double a, volatile double b) {
return (a + b) * (a + b);
}
a和b都是隨時(shí)可變的,所以上述代碼中的第一個(gè)a + b可能和第二個(gè)不同,導(dǎo)致出現(xiàn)非預(yù)期的結(jié)果。這種情況下,正確做法是將值賦予常規(guī)變量,然后再相乘:
double square(volatile double a, volatile double b) {
double c = a + b;
return c * c;
}
總結(jié)
mutable只能用與類變量,不能與const同時(shí)使用;在const修飾的方法中,mutable變量數(shù)值可以發(fā)生改變;volatile只是運(yùn)行期變量的值隨時(shí)可能改變,這種改變即可能來(lái)自其他線程,也可能來(lái)自外部系統(tǒng)。
以上就是聊聊C++的mutable和volatile的詳細(xì)內(nèi)容,更多關(guān)于C++ mutable和volatile的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語(yǔ)言手把手教你實(shí)現(xiàn)貪吃蛇AI(上)
這篇文章主要介紹了C語(yǔ)言手把手教你實(shí)現(xiàn)貪吃蛇AI,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01
C程序?qū)崿F(xiàn)整數(shù)的素?cái)?shù)和分解問(wèn)題
這篇文章主要介紹了C程序?qū)崿F(xiàn)整數(shù)的素?cái)?shù)和分解問(wèn)題,對(duì)于算法的學(xué)習(xí)有不錯(cuò)的借鑒價(jià)值,需要的朋友可以參考下2014-09-09
深入C++四種強(qiáng)制類型轉(zhuǎn)換的總結(jié)
本篇文章是對(duì)C++中四種強(qiáng)制類型轉(zhuǎn)換進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C語(yǔ)言利用棧實(shí)現(xiàn)對(duì)后綴表達(dá)式的求解
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言利用棧實(shí)現(xiàn)對(duì)后綴表達(dá)式的求解,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04
詳解C語(yǔ)言結(jié)構(gòu)體中的char數(shù)組如何賦值
這篇文章主要給大家介紹了關(guān)于C語(yǔ)言結(jié)構(gòu)體中的char數(shù)組如何賦值的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-03-03

