22

次の関数について考えてみます。

Foo foo(Foo x)
{
    return x;
}

return xコピーコンストラクターまたは移動コンストラクターを呼び出しますか?(ここでNRVOを脇に置いておきましょう。)

調査するために、Foo移動可能でコピー可能ではない単純なクラスを作成しました。

struct Foo
{
    Foo() = default;
    Foo(const Foo&) = delete;
    Foo(Foo&&) = default;
};

値パラメーターを値で返すときにmoveコンストラクターが呼び出された場合は、すべて問題ないはずです。return xしかし、現在のg ++​​コンパイラは、次のエラーメッセージで文句を言います。

error: deleted function 'Foo::Foo(const Foo&)'

に置き換えるreturn xreturn std::move(x)、すべて問題ありません。このことから、必要に応じて、値パラメーターからの移動を明示的に実行する必要があると結論付けます。g ++の動作は準拠していますか?

4

2 に答える 2

24

Fooの移動コンストラクターがある場合は、それを選択する必要があります。

関数パラメーターは、returnステートメントのコピーの省略から明示的に除外されます(FDIS§12.9p31、最初の箇条書き):

  • クラスreturn型の関数のreturnステートメントで、式が非揮発性の自動オブジェクトの名前である場合(関数またはcatch-clauseパラメーター以外)

ただし、次の段落では、movectorsを明示的に考慮に戻します。

ソースオブジェクトが関数パラメーターであり、コピーされるオブジェクトが左辺値で指定されていることを除いて、コピー操作の省略基準が満たされている、または満たされる場合、コピーのコンストラクターを選択するためのオーバーロード解決は次のようになります。最初は、オブジェクトが右辺値で指定されているかのように実行されます。…</p>

(強調は両方の引用で私のものです。)

于 2011-05-15T14:31:30.370 に答える
12

これは有効なコードです-G++の動作は準拠していません。MSVC10はこの動作をサポートしています。

于 2011-05-15T14:33:28.953 に答える