これは、オブジェクトの破棄と戻り値の最適化に関するC++の仕様に関する質問です。
クリーンアップの前にRVOが正しい値を返すことを期待できますstd::unique_ptr<>
か?
Foo
Bar()
{
std::unique_ptr<Foo> ptr = new Foo;
return *ptr;
}
これは、オブジェクトの破棄と戻り値の最適化に関するC++の仕様に関する質問です。
クリーンアップの前にRVOが正しい値を返すことを期待できますstd::unique_ptr<>
か?
Foo
Bar()
{
std::unique_ptr<Foo> ptr = new Foo;
return *ptr;
}
RVOの有無にかかわらず正しい値を返します(この場合、RVOはありません)。関数は具象Foo
を返すので、ポインタを破棄する前に戻り値に*ptr
コピーされます。
つまり、
Foo foo;
foo = Bar();
に似ています(より明確にするためにunique_ptrをアンラップします)
Foo foo;
Foo* ptr = new Foo;
foo = *ptr;
finally:
delete ptr;
関数がクラス型オブジェクトを返す場合、RVOは次の2つの状況でのみ許可されます。
したがって、コードはRVOをトリガーしません。
オブジェクトが自動ストレージで宣言されている場合Foo
、コンパイラーはRVOを実行できます。
Foo bar()
{
Foo foo;
return foo; // foo can be constructed directly as the returned object
}
何らかの理由でオブジェクトを作成する必要がありnew
、コピー操作を削除したい場合はstd::move
、を使用できます。これにより、式が右辺値に変更されます。
Foo bar()
{
std::unique_ptr<Foo> ptr(new Foo);
return std::move(*ptr); // No deep copy if Foo implements
// its own move constructor
}