3

次の例を検討してください。

#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);

(つまり、一時的に作成されず、copy-ctors が呼び出されません)。

ここで、上記の例で次のようにリストの初期化を使用するとします。

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

また

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

(1)および/または(2)が常に(つまり、コンパイラが「コピー省略」最適化を実行できる場合だけでなく)

    A x(5, nullptr);

(つまり、A の最初のコンストラクターが直接呼び出され、一時オブジェクトは作成されず、型 A のオブジェクトのコピーは実行されません)。

4

1 に答える 1

3

この答えは明らかに間違っているようです。コメントを参照してください。[dcl.init.list]/3 の 1 番目と 4 番目の箇条書きは、(1) コンストラクターを直接呼び出す (または集約初期化を実行する) ことを意味していると思います。

(1)と(2)が一時的なものを避けることを保証する標準には何もありません。どちらもコピー初期化であり、(1) は [dcl.init.list] p1 で定義されているコピー リスト初期化です。

リスト初期化は、直接初期化コンテキストまたはコピー初期化コンテキストで発生する可能性があります。直接初期化コンテキストでのリスト初期化は直接リスト初期化と呼ばれ、コピー初期化コンテキストでのリスト初期化はコピーリスト初期化と呼ばれます

どちらの場合もコピー初期化であり、[dcl.init] は移動を伴う可能性があることを示しています (これは省略できます)。

8.5/14,15:

フォームで発生する初期化

T x = a;

[...] はコピー初期化と呼ばれます。

フォームで発生する初期化

T x(a);

T x{a};

[...] は直接初期化と呼ばれます。

コンパイラが常に一時的なものを省略できるほど賢くない場合は、リストの初期化で一時的なものがないことを確認するために、直接リストの初期化を使用できます。つまり、

A x{5, nullptr};
于 2014-03-17T15:56:23.170 に答える