C++1z 値のコピー省略を保証

関数の戻り値のコピーを発生させない手法として、RVO (Return Value Optimization) やNRVO (Named Return Value Optimization) といった最適化がありました。

// RVOの最適化が動作した場合
struct Foo {};

Foo foo()
{
    return Foo();
}

Foo x = foo(); // Foo型のコピーコンストラクタが動作することなくxが初期化される
// NRVOの最適化が動作した場合
struct Foo { int value = 0; };

Foo foo()
{
    Foo y;
    y.value = 42;
    return y;
}

Foo x = foo(); // Foo型のコピーコンストラクタが動作することなくxが初期化される

しかし、これらの最適化はコンパイラに対して許可された動作であって、そのように最適化されることが保証されるものではありません。そのため、実際には(N)RVOによってコピーは起こらないけどコピーコンストラクタは用意しなければならない、といったことになります。

C++1zでは、このようなコピー省略を保証する仕組みが導入されます。そのため、オブジェクトの初期化のために使用するのであれば、コピーもムーブもできない型であっても、関数の戻り値として返せるようになります。

// C++1z
struct Foo {
    // Fooはコピーもムーブもできない
    Foo() = default;
    Foo(const Foo&) = delete;
    Foo(Foo&&) = delete;
};

Foo foo()
{
    return Foo();
}

Foo y = foo(); // OK

このコピー省略のためには、C++11で右辺値参照を導入するときに規定された「値カテゴリー (value category)」の仕様を利用します。prvalueという一時オブジェクトを表すカテゴリーの値を、オブジェクトの初期化のために使用する場合に、コピーが省略されるという仕様になります。

参照

お断り

この記事の内容は、C++1zが正式リリースされる際には変更される可能性があります。正式リリース後には、C++日本語リファレンスサイトcpprefjpの以下の階層の下に解説ページを用意する予定です。

更新履歴