RVO および NRVO の最適化が (適用可能な場合に) 標準で義務付けられていないのはなぜですか? たとえば、関数が何らかのオブジェクトを生成し、それを結果として返すという非常に一般的なケースがあります。コピー/移動コンストラクターは通常、RVO/NRVO のために省略されますが、それでも定義する必要があるため、多少混乱します。RVO/NRVO が標準に含まれていた場合、この場合、コピー/移動コンストラクターは不要になります。
1 に答える
コピー省略は、すべての実装ですべての場合に実装する必要があるため、標準では必須ではありません。
return-value-optimization とnamed -return-value-optimizationのケースを見てください。これを回すだけです:
std::string Func()
{
return std::string("foo");
}
この機能的に同一のコードに:
std::string Func()
{
std::string named("foo");
return named;
}
後者は、前者よりも多くのコンパイラを必要とします。コンパイラが異なれば、さまざまな状況で NRVO がサポートされます。確かに、彼らのほとんどはこの些細なケースでそれをサポートしていますが、そこには多くの異なるケースがあります. また、コンパイラが「ねじ込む」と言うだけで、最適化を完全に行わない場合もあります。
あなたの方法では、次のいずれかが必要になります。
コンパイラへの実装がどれほど困難であっても、該当するすべてのケースでコピー省略を強制する。したがって、すべてのコンパイラ作成者は、次のようなケースに対処する必要があります。
std::string Func(bool b) { if(b) { std::string named("foo"); return named; } else { std::string named("bar"); return named; } }
そのような場合、多くのコンパイラは NRVO を処理しません。これは単純なケースです。それよりもはるかに複雑になる可能性があります。
すべてのコンパイラを調べて、コピー省略が常に使用される一般的なケースのサブセットを見つけ、それらを標準で要件として指定します。それはまったくばかげています。実装の詳細に基づいて標準化します。それは決して良いことではありません。
C++17 では、特定のケースでコピー省略が保証される場合があることに注意してください。つまり、同じタイプのオブジェクトを初期化するためにテンポラリが使用されるときはいつでも、コピー/移動に省略が必要です。これにより、関数から不動オブジェクトを返すことが可能になります。