ローカル変数を返すとコピーが返され、元の変数が破棄されますか (NRVO)?
はじめに:
この質問は、 C でローカル変数を返す動作を調べています。具体的には、返されたオブジェクトがコピーであるか元のオブジェクトであるか、またそれがローカル変数の破棄にどのような影響を与えるかを調査します。
戻り値の最適化 (NRVO):
NRVO (戻り値の最適化という名前) を有効にすると、コンパイラーは return ステートメントを最適化し、不必要なコピーの構築やローカル変数の破壊を回避します。これは、戻りオブジェクトをターゲット ストレージに直接構築し、中間のコピーや移動のオーバーヘッドを排除することで実現されます。 NRVO は、ローカル変数に自動保存期間があり、戻り値の型と同じ型であるなど、特定の条件が満たされた場合に適用されます。
NRVO が有効な例:
次のコード:
class Test { public: Test(int p) { std::cout << "Constructor called" << std::endl; } ~Test() { std::cout << "Destructor called" << std::endl; } }; Test function() { Test t(5); // local variable with automatic storage duration return t; // return local variable } int main() { Test o = function(); return 0; }
NRVO を有効にすると、出力は次のようになります。 be:
Constructor called Destructor called
この場合、NRVO は return ステートメントを最適化し、オブジェクト o をローカル変数 t のストレージに直接構築します。コンストラクターは 1 回呼び出され、オブジェクト o に対して呼び出されるデストラクターは 1 つだけです。
NRVO が無効になっている例:
ただし、-fno-elide- を使用して NRVO を無効にできます。コンストラクターのコンパイラ フラグ。 NRVO を使用しない場合、コンパイラーはコピーの構築と破棄のステップを明示的に実行します。
Constructor called Constructor called Destructor called Destructor called
この場合、コンストラクターは 2 回呼び出されます (ローカル変数 t と戻りオブジェクト o に対して)。さらに、ローカル変数 t と戻りオブジェクト o は両方とも個別に破棄されます。
結論:
ローカル変数を返す動作は、NRVO が有効か無効かによって異なります。 NRVO を有効にすると、ローカル変数は最適化されなくなり、コンストラクターとデストラクターは戻りオブジェクトに対して 1 回だけ呼び出されます。 NRVO を使用しない場合、コピーの構築と破棄の手順が明示的に実行され、コンストラクターとデストラクターが複数回呼び出される可能性があります。
以上がC でローカル変数を返す場合、コピーの構築と破壊を避けるために名前付き戻り値の最適化 (NRVO) が利用されますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。