簡體   English   中英

C++17 中不可復制變量的成員初始化

[英]Member initialization for non-copyable variable in C++17

對不可復制變量(例如std::atomic<int> )執行成員初始化時,需要根據此處的答案使用direct-initialization而不是copy-initialization 但是,當我在g++ 7.4.0中打開-std=c++17時,似乎后者也能正常工作。

#include <atomic>

class A {
    std::atomic<int> a = 0;     // copy-initialization
    std::atomic<int> b{0};      // direct-initialization
};
$ g++ -c atomic.cc -std=c++11    // or c++14
atomic.cc:4:26: error: use of deleted function ‘std::atomic<int>::atomic(const std::atomic<int>&)’
     std::atomic<int> a = 0;     // copy-initialization

$ g++ -c atomic.cc -std=c++17
// no error

即使使用g++ 6.5.0編譯,它也失敗了-std=c++17 這里哪一個是正確的?

自 C++17 以來行為發生了變化,這要求編譯器省略std::atomic<int> a = 0; ,即保證復制省略

(強調我的)

在以下情況下,編譯器需要省略 class 對象的復制和移動構造,即使復制/移動構造函數和析構函數具有可觀察到的副作用。 對象直接構建到存儲中,否則它們將被復制/移動到。 復制/移動構造函數不需要存在或可訪問,因為語言規則確保不發生復制/移動操作,即使在概念上也是如此

詳細地說, std::atomic<int> a = 0; 執行 復制初始化

如果 T 是 class 類型,並且 other 的類型的 cv-unqualified 版本不是 T 或派生自 T,或者如果 T 是非類類型,但 other 的類型是 class 類型,用戶定義的轉換序列檢查可以從 other 的類型轉換為 T 的類型(或者如果 T 是 class 類型並且轉換 function 可用,則轉換為從 T 派生的類型)進行檢查,並通過重載決議選擇最佳的類型。 如果使用了轉換構造函數,則轉換結果是一個prvalue temporary (until C++17) prvalue expression (since C++17) ,然后用於直接初始化 object。

(強調我的)

如果 T 是 class 類型並且初始化程序是 prvalue 表達式,其 cv 非限定類型與 T 相同 class,則使用初始化程序表達式本身,而不是從它的臨時物化,來初始化目標 ZA8CFDE6331BD59EB2ACZFC6

這意味着a直接從0初始化,沒有要構造的臨時對象,也不再是要復制/移動的臨時對象。

在 C++17 之前,在概念上std::atomic<int> a = 0; 需要從0構造一個臨時的std::atomic ,然后該臨時用於復制構造a

在 C++17 之前甚至允許復制省略,這被認為是一種優化:

(強調我的)

這是一種優化:即使它發生並且沒有調用復制/ move (since C++11)構造函數,它仍然必須存在且可訪問(就好像根本沒有發生優化一樣),否則程序會出錯 -形成

這就是為什么 gcc 在 pre-c++17 模式下觸發診斷std::atomic<int> a = 0; .

(強調我的)

注意:上面的規則沒有指定優化:C++17 prvalues 和 temporaries 的核心語言規范與早期的 C++ 修訂版根本不同:不再有從. 描述 C++17 機制的另一種方式是“未實現的值傳遞”: prvalues 被返回並使用,而無需實現臨時的.

順便說一句:我想在g++ 6.5.0中有一個錯誤-std=c++17 並且已在以后的版本中修復。

這里哪一個是正確的?

7.4.0 是正確的。 對於這種情況,可以省略副本,這就是為什么可以。 (盡管這需要 )。

(有關詳細信息,請參閱https://en.cppreference.com/w/cpp/language/copy_initialization

暫無
暫無

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

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