c++中的volatile和variant關鍵字詳解

一、兩個長得有點像的變量

對volatile關鍵字,其實很多人隻是能用,知道用到啥處,但其實應用的原理並不知道。在一些多線程的通信中,往往是這個關鍵字應用到的場所,很多人也是如此想的。但其實這個想法是不準確的。volatile這個關鍵字的目的最初是針對硬件IO操作的,防止訪問IO操作中的緩存影響到真實的數據。但這個關鍵字的溢出效應是,多線程也可以應用這個原理(註意在多核和多CPU編程中有危險,但是在其它語言如Java中,得按具體的語言規范來決定),那麼反而在硬件IO中的應用成瞭一種比較少的應用場景。
在c++17中,還有一個長得和它類似的聯合體variant,如果有其它語言中var變量的使用,就大概明白瞭這是個啥玩意兒。既然是聯合體,那麼就明白瞭這個關鍵字的用處瞭,也就是說,它可以表示明確的類型定義,而在前面提到的std::any則不是。看一下在c++17中它的標準定義:

template <class... Types>
class variant;

之所以把它們兩個搞在一起,是有的時候兒新手小菜鳥可能會把兩個傻傻分不清。

二、二者的功能

類模板 std::variant 表示一個類型安全的聯合體,它表示可以擁有其中的任何一個類型或者無值,它不能保有引用、數組或者void,如果表示一個空值,也要用std::variantstd::monostate 代替。同樣,在默認構造時,默認保有聯合體的第一個類型。面std::volatile則更多傾向於一個編譯器的優化選項處理,它會防止變量被編譯器緩存。正如前面所講,這個在多線程中應用的比較多,但其實他更安全的應用其實是在硬件IO操作中。
這麼看來,這二者的區別還是相當明顯的,別看長得乍一看有點像,但還真不是一嘛事兒。隻要寫一回代碼估計就記清楚瞭。或者簡單的記憶成volatile是一個關鍵字,而variant是一個復合類型,是一個聯合體,是一個類模板。

三、應用實例

看一個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); // 錯誤: [int, float] 中無 double
//  std::get<3>(v);      // 錯誤:合法下標值為 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"); // 轉換構造函數在無歧義時起作用
    x = "def"; // 轉換賦值在無歧義時亦起作用
 
    std::variant<std::string, void const*> y("abc");
    // 傳遞 char const * 時轉換成 void const *
    assert(std::holds_alternative<void const*>(y)); // 成功
    y = "xyz"s;
    assert(std::holds_alternative<std::string>(y)); // 成功
}

volatitle這個關鍵字給一個判斷的例程,就不給多線程的例程瞭,這玩意兒一般來說還是要小心使用,在多核,內存序未知的情況下,還是不用為妙,X86因為一些歷史原因,用起來還是比較可以接受的:

#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';
}

這個關鍵字對從Java轉過來的開發人員可能有非常大的迷惑性,二者的理解意義還是有比較大的不同的。把內存序掌握好瞭,就知道為什麼在X86的PC上跑一般沒有問題的原因,如果還是無法清楚,就好好看看c++標準中對內存序的支持。這個一定要搞明白,搞不明白的話,可能不會影響到編程,但會影響到對標準的認知。

四、總結

俗話說:“看一遍不如寫一遍”,這句話在計算機行業應該是非常合適的。計算機技術是一門理論科學與實踐高度結合的技術,理論是源泉,實踐是根本,互相反饋,不斷迭代,這才是真正提高編程水平的王道。
努力吧,歸來的少年

到此這篇關於c++中的volatile和variant關鍵字詳解的文章就介紹到這瞭,更多相關c++ volatile和variant關鍵字內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: