7

オブジェクトが関数から値で返されるとき、それらのコピーコンストラクターが呼び出されることを理解しています。クラスに削除されたコピーコンストラクタがある場合、値による戻りは失敗します。

struct X {
    X(const X &) = delete;
};

X f() {
   return X{};
}

error: call to deleted constructor of 'X'

C ++ 11は、拡張初期化子を提供します。そして私はSOの投稿のどこかでこれを読んだ

X f() {
    return {};
}

と同じです

X f() {
    return X{};
}

では、なぜ以下のコードでエラーが発生しないのですか?それは合格し、mainで関数を呼び出すことさえできます:

struct D {
   D(const D &) = delete;
};

D f() { return {}; }

int main()
{
   f();
}

これがデモです。エラーは報告されません。コピーコンストラクターを呼び出す必要があると思うので、それは奇妙だと思います。エラーが発生しない理由を誰かが説明できますか?

4

1 に答える 1

12

そして、私はSOの投稿のどこかで、この[...]は[...]と同じであると読みました。

彼らは間違っていた。それらはていますが、同じではありません。

braced-init-listを使用すると、戻り値をインプレースで初期化できます。一時を作成する場合、実行しているのは、一時を作成してから、それを戻り値にコピーすることです。その塩に値するコンパイラはそれを排除しますが、それでもコピーコンストラクタはアクセス可能でなければなりません。

ただし、braced-init-listは戻り値をインプレースで初期化するため、コピーコンストラクターにアクセスする必要はありません。

標準から、セクション6.6.3、p2:

braced-init-listを含むreturnステートメントは、指定された初期化子リストからのcopy-list-initialization(8.5.4)によって、関数から返されるオブジェクトまたは参照を初期化します。

「copy-list-initialization」は「copy-initialization」とは似ていないことに注意してください。コピーを行わないため、アクセス可能なコピーコンストラクターは必要ありません。「copy-list-initialization」と「direct-list-initialization」の唯一の違いは、前者がexplicitコンストラクターを窒息させることです。

于 2013-03-10T22:20:14.010 に答える