簡體   English   中英

為什么使用 C++17 禁用 std::atomic 的復制省略不起作用?

[英]Why disabling copy elision for std::atomic doesn't work using C++17?

對於std::atomic復制構造函數被刪除,並且由於復制省略,這應該只用 C++17 和更高版本編譯:

std::atomic<int> t_int = 1; 

我預計它不會使用-fno-elide-constructors標志進行編譯,但它仍然可以編譯:

https://godbolt.org/z/nMvG5vTrK

為什么是這樣?

C++17 並不僅僅說以前可選的返回值優化現在是強制性的。 語言的實際描述發生了變化,因此一開始就不再創建臨時的 object。

因此,自 C++17 以來,不再有可以省略的構造函數調用。 因此, -fno-elide-constructors不添加任何臨時創建是有道理的。 那將違反語言規則。

在 C++17 之前,該語言描述了創建一個臨時變量 object,從中初始化變量,然后添加允許編譯器省略這個臨時變量。 因此,無論是否使用-fno-elide-constructors ,編譯器都會通過省略或不省略臨時副本來表現出符合標准的行為。

我預計它不會使用 -fno-elide-constructors 標志進行編譯,

給定標志對 C++17 及以后的返回值優化(又名 RVO)沒有影響。 這是因為它不再被視為優化(來自 C++17),而是一種語言保證

來自強制復制 elison

在以下情況下,編譯器需要省略 class 對象的復制和移動構造,即使復制/移動構造函數和析構函數具有可觀察到的副作用。 對象直接構建到存儲中,否則它們將被復制/移動到. 復制/移動構造函數不需要存在或可訪問

  • object 的初始化中,當初始化表達式是與變量類型相同的 class 類型(忽略 cv 限定)的純右值時:

(強調我的)

這意味着t_int是直接從prvalue 1構造的。 標志-fno-elide-constructors對 RVO 沒有影響,這與 NRVO 不同。 因此,被刪除的復制構造函數對您的情況沒有影響。

也許一個例子可能有助於說明相同的,

struct Custom 
{
    public:
      Custom(int p): m_p(p)
      {
          std::cout<<"converting ctor called"<<std::endl;
      }
      Custom(const Custom&) = delete; //deleted copy ctor
    private:
      int m_p = 0;
};
int main()
{
    Custom c = 1; //works in C++17 but not in Pre-C++17
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM