簡體   English   中英

列表初始化和復制省略

[英]List initialization and copy elision

請考慮以下示例:

#include <cstdlib>
struct A
{
    A(int, char*){};
    A(const A&){ printf("copy-ctor\n"); }
};
int main()
{
    A x = A(5, nullptr);
}

根據8.5.16(C ++ 11標准)的行

    A x = A(5, nullptr);

被視為

    A x(A(5, nullptr));

(即創建類型A的臨時對象並將其傳遞給類型A的copy-ctor以初始化x)。 然后根據12.8.31編譯器允許( 但不強制 )執行稱為“復制省略”的優化以消除類型A的臨時創建,這有效地使該行代碼成為

    A x(5, nullptr);

(即沒有臨時創建,沒有復制者稱呼)。

現在,假設我在上面的示例中使用列表初始化,如下所示:

    A x = {5, nullptr}; // (1)

要么

    A x = A{5, nullptr}; // (2)

有人可以引用C ++ 11標准適當的階段圖來確認或否認(1)和/或(2) 總是 (即不僅在編譯器可以做“復制省略”優化時)被視為

    A x(5, nullptr);

(即直接調用A的第一個構造函數,不創建臨時值,不執行類型A對象的復制)。

這個答案顯然是錯誤的,這讓我感到驚訝。 查看評論。 我認為[dcl.init.list] / 3的第一個和第四個要點是什么意思(1)直接調用構造函數(或執行聚合init),沒有臨時的。

標准中沒有任何內容可以保證(1)和(2)避免臨時。 它們都是復制初始化,(1)是[dcl.init.list] p1定義的復制列表初始化:

列表初始化可以在直接初始化或復制初始化上下文中進行; 直接初始化上下文中的列表初始化稱為直接列表初始化 ,復制初始化上下文中的列表初始化稱為復制列表初始化

在這兩種情況下都是復制初始化,[dcl.init]表示可能涉及移動(可以省略)。

8.5/14,15

在表單中發生的初始化

T x = a;

[...]稱為復制初始化。

表單中發生的初始化

T x(a);

T x{a};

[...]稱為直接初始化。

如果您的編譯器不夠智能以至於總是忽略臨時,那么為了確保沒有臨時的列表初始化,您可以使用direct-list-initialization,即

A x{5, nullptr};

暫無
暫無

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

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