聊聊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)該對類/對象帶來副作用。
考慮一個(gè)mutable
的使用場景:呼叫系統(tǒng)中存有司機(jī)(Driver)的信息,為了保護(hù)司機(jī)的隱私,司機(jī)對外展現(xiàn)的聯(lián)系號碼每隔五分鐘從空閑號碼池更新一次。根據(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
方法中不允許對常規(guī)成員進(jìn)行變動,但mutable
成員不受此限制。對Driver
類來說,其固有屬性(姓名、年齡、真實(shí)手機(jī)號等)未發(fā)生改變,符合const
修飾。mutable
讓一些隨時(shí)可變的展示屬性能發(fā)生改變,達(dá)到了靈活編程的目的。
volatile
volatile
用于修飾成員或變量,指示其修飾對象可能隨時(shí)變化,編譯器不要對所修飾變量進(jìn)行優(yōu)化(緩存),每次取值應(yīng)該直接讀取內(nèi)存。由于volatile
的變化來自運(yùn)行期,其可以與const
一起使用。兩者一起使用可能讓人費(fèi)解,如果考慮場景就容易許多:CPU和GPU通過映射公用內(nèi)存中的同一塊,GPU可能隨時(shí)往共享內(nèi)存中寫數(shù)據(jù)。對CPU上的程序來說,const
修飾變量一直是右值,所以編譯通過。但其變量內(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)都會檢查內(nèi)存中的值,達(dá)到同步的效果。
需要注意的是,volatile
的值可能隨時(shí)會變,期間會導(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í)可能改變,這種改變即可能來自其他線程,也可能來自外部系統(tǒng)。
以上就是聊聊C++的mutable和volatile的詳細(xì)內(nèi)容,更多關(guān)于C++ mutable和volatile的資料請關(guān)注腳本之家其它相關(guān)文章!
- C++關(guān)鍵字volatile學(xué)習(xí)筆記
- C++中的volatile關(guān)鍵字及其作用
- c++中的volatile和variant關(guān)鍵字詳解
- C++中volatile和mutable關(guān)鍵字用法詳解
- C++中volatile關(guān)鍵字的使用詳解以及常見的誤解
- C++中const、volatile、mutable使用方法小結(jié)
- C++中mutable與volatile的深入理解
- C++中volatile關(guān)鍵字及常見的誤解總結(jié)
- 淺談C++中的mutable和volatile關(guān)鍵字
- C++中volatile限定符的實(shí)現(xiàn)示例
相關(guān)文章
C++實(shí)現(xiàn)一個(gè)簡易版的事件(Event)的示例代碼
之前在?windows系統(tǒng)中開發(fā)應(yīng)用時(shí),?遇到需要進(jìn)行線程同步的時(shí)候幾乎都是使用的事件內(nèi)核對象?Event。本文為大家整理了C++實(shí)現(xiàn)一個(gè)簡易版的事件(Event)的相關(guān)資料,需要的可以參考一下2022-11-11C++二叉樹的前序中序后序非遞歸實(shí)現(xiàn)方法詳細(xì)講解
前序遍歷的順序是根、左、右。任何一顆樹都可以認(rèn)為分為左路節(jié)點(diǎn),左路節(jié)點(diǎn)的右子樹。先訪問左路節(jié)點(diǎn),再來訪問左路節(jié)點(diǎn)的右子樹。把訪問左路節(jié)點(diǎn)的右子樹看成一個(gè)子問題,就可以完整遞歸訪問了2023-03-03C語言實(shí)現(xiàn)點(diǎn)菜系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)點(diǎn)菜系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06