コピー省略
コピーおよびムーブ (C++11以上)コンストラクタを省略し、ゼロコピーの値渡しセマンティクスを実現します。
説明
必須のコピー/ムーブ省略以下の状況において、コンパイラは、たとえコピー/ムーブコンストラクタおよびデストラクタが観察可能な副作用を持っていたとしても、クラスオブジェクトのコピーおよびムーブ構築を省略することが要求されます。 オブジェクトは、それらのコピー/ムーブ先の記憶域に、直接構築されます。 コピー/ムーブコンストラクタは存在する必要もアクセス可能である必要もありません。 T f() {
return T();
}
f(); // T のデフォルトコンストラクタが一度だけ呼ばれます。
T x = T(T(f())); // x を初期化するために T のデフォルトコンストラクタが一度だけ呼ばれます。
struct C { /* ... */ };
C f();
struct D;
D g();
struct D : C {
D() : C(f()) { } // 基底クラス部分オブジェクトを初期化するときは省略は行われません。
D(int) : D(g()) { } // 初期化中の D オブジェクトが何らかの別のクラスの
// 基底クラス部分オブジェクトかもしれないため省略は行われません。
};
ノート: 上記のルールは最適化を規定しているのではありません。 C++17 コア言語の prvalue および一時オブジェクトの仕様は C++ の以前の版のそれとは根本的に異なります。 コピー/ムーブ元の一時オブジェクトはもはや存在しません。 C++17 の仕組みを説明する別の方法は「具体化されない値渡し」です。 prvalue は一時オブジェクトを一度も具体化することなく返され、使用されます。 |
(C++17以上) |
必須でないコピー/ムーブ省略
以下の状況において、コンパイラは、たとえコピー/ムーブ (C++11以上)コンストラクタおよびデストラクタが観察可能な副作用を持っていたとしても、クラスオブジェクトのコピーおよびムーブ (C++11以上)構築を省略することが許されますが、要求はされません。 オブジェクトは、それらのコピー/ムーブ先の記憶域に、直接構築されます。 これは最適化です。 コピー/ムーブ (C++11以上)コンストラクタは、たとえ呼ばれないときでも、 (最適化がまったく行われなかった場合のように) 存在し、アクセス可能でなければなりません。 そうでなければ、プログラムは ill-formed です。
- return 文において、被演算子が自動記憶域期間を持つ非 volatile オブジェクトの名前であり、それが関数の引数または catch 節の引数でなく、関数の戻り値の型と同じクラス型 (cv 修飾は無視します) であるとき。 コピー省略のこの変種は NRVO (named return value optimization; 名前付き戻り値の最適化) と言います。
|
(C++17未満) |
|
戻り値の最適化は必須であり、もはやコピー省略とみなされません。 上を参照してください。 |
(C++17以上) |
|
(C++11以上) |
|
(C++20以上) |
コピー省略が発生したとき、処理系は省略されたコピー/ムーブ (C++11以上)操作のソースとターゲットを単に同じオブジェクトを参照する2つの異なる方法として扱い、そのオブジェクトの破棄は最適化がなかった場合に2つのオブジェクトが破棄されたであろうときに発生します (ただし、選択されたコンストラクタの引数がオブジェクト型への右辺値参照の場合は、破棄はターゲットが破棄されたであろうときに発生します) (C++17以上)。
複数のコピーを省略するために複数のコピー省略が連鎖することがあります。
|