/Zc:nrvo
(オプションの NRVO を制御する)
/Zc:nrvo
コンパイラ オプションは、標準 C++ の省略可能な名前付き戻り値の最適化 (NRVO) のコピーまたは移動の省略可能な動作を制御します。
構文
/Zc:nrvo
[-
]
解説
Visual Studio 2022 バージョン 17.4 以降では、 /Zc:nrvo
コンパイラ オプションを使用して、省略可能なコピーまたは移動のエリジオン動作を明示的に有効にすることができます。 このオプションは既定ではオフになっていますが、 /O2
オプション、 /permissive-
オプション、または /std:c++20
以降を使用してコンパイルすると自動的に設定されます。 /Zc:nrvo
では、可能な限りコピーと移動のエリシオンが実行されます。 オプションのコピーまたは移動のエリジオンは、 /Zc:nrvo-
オプションを使用して明示的に無効にすることもできます。 これらのコンパイラ オプションは、省略可能なコピーまたは移動のエリシオンのみを制御します。 必須のコピーまたは移動のエリジオン (C++ 標準で指定) を無効にすることはできません。
必須のコピーと移動のエリシオン
C++ 標準では、戻り値が return ステートメントの一部として初期化されるときに、コピーまたは移動の省略が必要です。 たとえば、関数が return ExampleType();
を使用して返されるExampleType
を返す場合に必要です。 MSVC コンパイラは、/Zc:nrvo-
の下でも、必要な場合は常にreturn
ステートメントのコピーと移動の省略を実行します。
省略可能なコピーと移動のエリシオン
return
ステートメントにプリミティブ以外の型の式が含まれている場合、その実行により、式の結果が呼び出し元の関数の戻りスロットにコピーされます。 コンパイラは、返された型のコピーコンストラクターまたは移動コンストラクターを呼び出します。 次に、関数が終了すると、関数ローカル変数のデストラクターが呼び出されます。これには、式に名前が付けられた変数が含まれます。
C++ 標準では、コンパイラは必要に応じて、呼び出し元の関数のリターン スロットで返されたオブジェクトを直接構築できます (ただし、必要ありません)。 この構築では、return
ステートメントの一部として実行されるコピーコンストラクターまたは移動コンストラクターがスキップ (またはスライド) されます。 他のほとんどの最適化とは異なり、この変換はプログラムの出力に観測可能な影響を与える可能性があります。 つまり、コピーまたは移動コンストラクターと関連付けられたデストラクターは、1 回少ない時間で呼び出されます。 標準では、コンパイラがすべてのケースでコンストラクターを省略した場合でも、返される名前付き変数に定義済みのコピーまたは移動コンストラクターが必要です。
Visual Studio 2022 バージョン 17.4 より前のバージョンでは、最適化が無効になっている場合 ( /Od
または #pragma optimize("", off)
マークされた関数など) では、コンパイラは必須のコピーと移動の省略のみを実行します。 /O2
では、古いコンパイラは、最適化された関数の名前付き変数の戻り時に省略可能なコピーまたは移動を実行します。これらの条件がすべて満たされた場合:ループや例外処理がなく、有効期間が重複する複数のシンボルを返しません。型のコピーまたは移動コンストラクターには既定の引数はありません。
Visual Studio 2022 バージョン 17.4 では、/O2
、/permissive-
、または/std:c++20
以降のオプションを使用して、コンパイラが省略可能なコピーまたは移動のエリシオンを/Zc:nrvo
の下で実行する場所の数が増えます。 /Zc:nrvo
では、任意の関数に対する名前付き変数の戻り時に省略可能なコピーまたは移動のエリジオンが実行されます。ループまたは例外処理がない場合、ループから変数を返します。例外処理があります。返される型のコピーまたは移動コンストラクターには既定の引数があります。 オプションのコピーまたは移動のエリジオンは、 /Zc:nrvo-
が適用されたとき、または関数が有効期間が重複する複数のシンボルを返すとき、または名前付き変数のスローに対して実行されることはありません。
/Zc:nrvo
での必須および省略可能なコピーのエリジオンの詳細と例については、C++ チーム ブログのコピーと移動のエリシオンを参照してください。
このコンパイラ オプションを Visual Studio で使用するには
プロジェクトの [プロパティ ページ] ダイアログ ボックスを開きます。 詳細については、Visual Studio での C++ コンパイラとビルド プロパティの設定に関する記事を参照してください。
[構成プロパティ]>[C/C++]>[コマンド ライン] プロパティ ページを選択します。
[追加のオプション] で、
/Zc:nrvo
または/Zc:nrvo-
を追加します。 [OK] または [適用] を選択して、変更内容を保存します。