c++中的volatile和variant關(guān)鍵字詳解
一、兩個(gè)長(zhǎng)得有點(diǎn)像的變量
對(duì)volatile關(guān)鍵字,其實(shí)很多人只是能用,知道用到啥處,但其實(shí)應(yīng)用的原理并不知道。在一些多線(xiàn)程的通信中,往往是這個(gè)關(guān)鍵字應(yīng)用到的場(chǎng)所,很多人也是如此想的。但其實(shí)這個(gè)想法是不準(zhǔn)確的。volatile這個(gè)關(guān)鍵字的目的最初是針對(duì)硬件IO操作的,防止訪問(wèn)IO操作中的緩存影響到真實(shí)的數(shù)據(jù)。但這個(gè)關(guān)鍵字的溢出效應(yīng)是,多線(xiàn)程也可以應(yīng)用這個(gè)原理(注意在多核和多CPU編程中有危險(xiǎn),但是在其它語(yǔ)言如Java中,得按具體的語(yǔ)言規(guī)范來(lái)決定),那么反而在硬件IO中的應(yīng)用成了一種比較少的應(yīng)用場(chǎng)景。
在c++17中,還有一個(gè)長(zhǎng)得和它類(lèi)似的聯(lián)合體variant,如果有其它語(yǔ)言中var變量的使用,就大概明白了這是個(gè)啥玩意兒。既然是聯(lián)合體,那么就明白了這個(gè)關(guān)鍵字的用處了,也就是說(shuō),它可以表示明確的類(lèi)型定義,而在前面提到的std::any則不是??匆幌略赾++17中它的標(biāo)準(zhǔn)定義:
template <class... Types> class variant;
之所以把它們兩個(gè)搞在一起,是有的時(shí)候兒新手小菜鳥(niǎo)可能會(huì)把兩個(gè)傻傻分不清。
二、二者的功能
類(lèi)模板 std::variant 表示一個(gè)類(lèi)型安全的聯(lián)合體,它表示可以擁有其中的任何一個(gè)類(lèi)型或者無(wú)值,它不能保有引用、數(shù)組或者void,如果表示一個(gè)空值,也要用std::variantstd::monostate 代替。同樣,在默認(rèn)構(gòu)造時(shí),默認(rèn)保有聯(lián)合體的第一個(gè)類(lèi)型。面std::volatile則更多傾向于一個(gè)編譯器的優(yōu)化選項(xiàng)處理,它會(huì)防止變量被編譯器緩存。正如前面所講,這個(gè)在多線(xiàn)程中應(yīng)用的比較多,但其實(shí)他更安全的應(yīng)用其實(shí)是在硬件IO操作中。
這么看來(lái),這二者的區(qū)別還是相當(dāng)明顯的,別看長(zhǎng)得乍一看有點(diǎn)像,但還真不是一嘛事兒。只要寫(xiě)一回代碼估計(jì)就記清楚了?;蛘吆?jiǎn)單的記憶成volatile是一個(gè)關(guān)鍵字,而variant是一個(gè)復(fù)合類(lèi)型,是一個(gè)聯(lián)合體,是一個(gè)類(lèi)模板。
三、應(yīng)用實(shí)例
看一個(gè)variant的例程:
#include <variant> #include <string> #include <cassert> int main() { std::variant<int, float> v, w; v = 12; // v 含 int int i = std::get<int>(v); w = std::get<int>(v); w = std::get<0>(v); // 與前一行效果相同 w = v; // 與前一行效果相同 // std::get<double>(v); // 錯(cuò)誤: [int, float] 中無(wú) double // std::get<3>(v); // 錯(cuò)誤:合法下標(biāo)值為 0 與 1 try { std::get<float>(w); // w 含 int 而非 float :將拋出 } catch (const std::bad_variant_access&) {} using namespace std::literals; std::variant<std::string> x("abc"); // 轉(zhuǎn)換構(gòu)造函數(shù)在無(wú)歧義時(shí)起作用 x = "def"; // 轉(zhuǎn)換賦值在無(wú)歧義時(shí)亦起作用 std::variant<std::string, void const*> y("abc"); // 傳遞 char const * 時(shí)轉(zhuǎn)換成 void const * assert(std::holds_alternative<void const*>(y)); // 成功 y = "xyz"s; assert(std::holds_alternative<std::string>(y)); // 成功 }
volatitle這個(gè)關(guān)鍵字給一個(gè)判斷的例程,就不給多線(xiàn)程的例程了,這玩意兒一般來(lái)說(shuō)還是要小心使用,在多核,內(nèi)存序未知的情況下,還是不用為妙,X86因?yàn)橐恍v史原因,用起來(lái)還是比較可以接受的:
#include <iostream> #include <type_traits> int main() { std::cout << boolalpha; std::cout << std::is_volatile<int>::value << '\n'; std::cout << std::is_volatile<volatile int>::value << '\n'; }
這個(gè)關(guān)鍵字對(duì)從Java轉(zhuǎn)過(guò)來(lái)的開(kāi)發(fā)人員可能有非常大的迷惑性,二者的理解意義還是有比較大的不同的。把內(nèi)存序掌握好了,就知道為什么在X86的PC上跑一般沒(méi)有問(wèn)題的原因,如果還是無(wú)法清楚,就好好看看c++標(biāo)準(zhǔn)中對(duì)內(nèi)存序的支持。這個(gè)一定要搞明白,搞不明白的話(huà),可能不會(huì)影響到編程,但會(huì)影響到對(duì)標(biāo)準(zhǔn)的認(rèn)知。
四、總結(jié)
俗話(huà)說(shuō):“看一遍不如寫(xiě)一遍”,這句話(huà)在計(jì)算機(jī)行業(yè)應(yīng)該是非常合適的。計(jì)算機(jī)技術(shù)是一門(mén)理論科學(xué)與實(shí)踐高度結(jié)合的技術(shù),理論是源泉,實(shí)踐是根本,互相反饋,不斷迭代,這才是真正提高編程水平的王道。
努力吧,歸來(lái)的少年
到此這篇關(guān)于c++中的volatile和variant關(guān)鍵字詳解的文章就介紹到這了,更多相關(guān)c++ volatile和variant關(guān)鍵字內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言聯(lián)合體類(lèi)型的實(shí)現(xiàn)
聯(lián)合體也是一種構(gòu)造數(shù)據(jù)類(lèi)型,和結(jié)構(gòu)體類(lèi)型一樣,它也是由各種不同類(lèi)型的數(shù)據(jù)組成,本文主要介紹了C語(yǔ)言聯(lián)合體類(lèi)型的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-02-02C++數(shù)據(jù)結(jié)構(gòu)與算法之雙緩存隊(duì)列實(shí)現(xiàn)方法詳解
這篇文章主要介紹了C++數(shù)據(jù)結(jié)構(gòu)與算法之雙緩存隊(duì)列實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了雙緩存隊(duì)列的原理、實(shí)現(xiàn)方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2017-08-08cocos2dx-3.10 C++實(shí)現(xiàn)滾動(dòng)數(shù)字
這篇文章主要為大家詳細(xì)介紹了cocos2dx-3.10 C++實(shí)現(xiàn)滾動(dòng)數(shù)字效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-09-09C語(yǔ)言中#pragma?pack(1)的用法與注意點(diǎn)
#pragma用于指示編譯器完成一些特定的動(dòng)作,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中#pragma?pack(1)的用法與注意點(diǎn)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02C++鏈表實(shí)現(xiàn)通訊錄設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了C++鏈表實(shí)現(xiàn)通訊錄設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06