ベストアンサー1
導入
技術的な概要については -この回答へスキップ。
コピー省略が発生する一般的なケースとしては、この回答へスキップ。
コピー省略は、特定の状況で余分な(潜在的にコストのかかる)コピーを防ぐために、ほとんどのコンパイラによって実装される最適化です。これにより、値を返すことや値渡しが実際に可能になります(制限が適用されます)。
これは、as-if ルールを省略する (笑) 唯一の最適化形式です。オブジェクトのコピー/移動に副作用がある場合でも、コピー省略を適用できます。
以下の例は、ウィキペディア:
struct C {
C() {}
C(const C&) { std::cout << "A copy was made.\n"; }
};
C f() {
return C();
}
int main() {
std::cout << "Hello World!\n";
C obj = f();
}
コンパイラと設定に応じて、次の出力はすべて有効です。
こんにちは世界!
コピーが作成されました。
コピーが作成されました。
こんにちは世界!
コピーが作成されました。
「こんにちは世界」
これは、作成できるオブジェクトの数が少なくなることも意味するため、特定の数のデストラクタが呼び出されることに依存することもできません。コピー/移動コンストラクタまたはデストラクタが呼び出されることを依存できないため、それらの内部に重要なロジックを含めるべきではありません。
コピーまたは移動コンストラクタの呼び出しが省略された場合、そのコンストラクタは存在し、アクセス可能である必要があります。これにより、コピー省略によって、たとえばプライベートまたは削除されたコピー/移動コンストラクタを持つなどの理由で通常はコピーできないオブジェクトのコピーが許可されないことが保証されます。
C++17 : C++17 以降では、オブジェクトが直接返される場合にコピー省略が保証され、この場合、コピーまたは移動コンストラクターがアクセス可能であったり存在したりする必要はありません。
struct C {
C() {}
C(const C&) { std::cout << "A copy was made.\n"; }
};
C f() {
return C(); //Definitely performs copy elision
}
C g() {
C c;
return c; //Maybe performs copy elision
}
int main() {
std::cout << "Hello World!\n";
C obj = f(); //Copy constructor isn't called
}