対とg ++は最近のコンパイラのデフォルトでは、コードを改善するために、コピーの数を減らすためにRVO(戻り値の最適化、戻り値の最適化)、NRVO(名前付き戻り値の最適化、名前の戻り値の最適化)とは、コピー省略(コピーの省略)技術を使用しています業務の効率化
注1:コンパイラは、この最適化をオフにするオプションを提供していないVS、デバッグまたはリリースのいずれかは、最適化開きます
:注2でG ++コンパイラオプションを:-fno-Elideの-コンストラクタの最適化を閉じます
RVO
コンパイラのサポートのほとんどは
する#include <stdio.hの> クラスA { パブリック: () { のprintf(" %P構築する\ n "、この)。 } A(CONST A&CP) { のprintf(" %Pコピー構築する\ n "、この)。 } 〜A() { のprintf(" %Pを破壊する\ n "、この)。 } }。 下駄は、() { 戻り()。 } INT メイン() { { A = 下駄()。 } 戻り 0 。 }
次のようにバージョンVS2008 + g ++およびコードに一度だけのみコンストラクタとデストラクタが呼び出され、出力結果は、次のとおり
0x7ffe9d1edd0f構築 0x7ffe9d1edd0f破壊を
次のように最適化オプションがオフになっている-fno-Elideの-コンストラクタと結合G ++では、出力結果は、次のとおり
0x7ffc46947d4f構築し 、機能下駄に//呼び出し、引数なしのコンストラクタA()、一時変数temp構築するために 構築し、コピー0x7ffc46947d7fを(パラメータとして渡され、一時変数tempに//機能下駄のreturn文を、コピーコンストラクタAを呼び出しますconst A&CP)の戻り値のRETを構築 0x7ffc46947d4f破壊を//下駄は、そのデストラクタA〜()を呼び出し、関数の戻り値ステートメントの後に、一時変数tempのライフサイクルの終わりに実行され 0x7ffc46947d7eコピーを構築し、上に戻り、最後下駄//関数呼び出しをメイン関数の後、変数RETの戻り値は、パラメータとして渡され、コピーコンストラクタA(のconst A&CP)A構築変数呼び出します 0x7ffc46947d7f破壊// A、A =下駄()文の終了後、返り値retのライフサイクルを終わり、そのデストラクタ関数〜A() 0x7ffc46947d7e破壊// A Aスコープ外とすることで、ライフサイクルの終わりに、そのデストラクタ関数〜A()
注:一時的な変数temp、戻り値retのは、匿名の変数であります
ここではどのような最適化の挙動をシミュレートするためのC ++コードで:
する#include < 新しい新規 > A&下駄(ボイド *のP) { // p型メモリは外部から渡され、関数が戻った後、まだ有効である場合、戻り値は、このよう&Aできる // VS、次のコードのように書くこともできます。 // A&O = *((* A)P); // OA :: A(); // Oを返す。 返す * 新しい新しい(P)Aを(); // 配置新しい新しい } int型のmain() { { CHAR BUF〔はsizeof (A)]; A&A = 下駄(BUF) 。A〜A(); } 戻り 0 。 }
NRVO
VS2005 +バージョンはサポートされています
上記のコードを変更する、下駄を達成するように変更:
下駄()のような { など。 リターンがあります。 }
バージョンVS2005 + g ++およびコードに唯一のコールのみコンストラクタとデストラクタであり、以下のように、出力結果は、次のとおり
0x7ffe9d1edd0f構築 0x7ffe9d1edd0f破壊を
最適化オプションがオフになっている-fno-Elideの-コンストラクタと同じ上記の結果と結合されたG ++、中
0x7ffc46947d4f構築 0x7ffc46947d7fが構築コピー 0x7ffc46947d4f破壊 構築コピー0x7ffc46947d7e 0x7ffc46947d7f破壊 0x7ffc46947d7e破壊を
注意:変数A、Oという名前の変数を持っています
しかし、VC6で、出力は次のようになります。
18fec4構築 機能で//下駄を、引数なしのコンストラクタ呼び出しはO一時変数構築するために()を機能さ 18ff44コピーが構築 機能の//下駄のreturn文を、パラメータとして渡された一時変数とOのコピーコンストラクタのAを(呼び出しますconst A&CP)の戻り値のRETを構築 18fec4破壊を //下駄は、そのデストラクタA〜()を呼び出し、人生の終わりoを関数のreturn文、一時的な変数の後に実行されて 18ff44破壊スコープの生活の外にあることを// A Aをサイクルが終了し、そのデストラクタを呼び出す〜A()
ここでVC6に何の行動をシミュレートするためのC ++コードで:
する#include < 新しい新規 > A&下駄(ボイド *のP) { O; // p個のメモリが外部から渡されるので、関数復帰後も有効であり、戻り値もよい従って&A // VS、次のコードをさらに書くことができる: // A&T * =((A *)P); // の:: A TA(O); // 戻りTは、 戻り * 新しい新しい(P)A(O); // 配置新しい新しい } int型メイン() { { チャー BUF〔はsizeof (A)]; A&A = 下駄(BUF) 。A〜A(); } 戻り 0 ; }
注: 2回の合計は、コンストラクタとデストラクタを呼び出すために最後にして対とg ++と比較すると、VC6は変数にのみ戻り値を最適化し、Oではないというローカル変数のコピーは、離れて最適化されます
コピー省略
コンパイラのサポートのほとんどは
通常、次のとおりです。値型を渡すコンストラクタパラメータを呼び出します
ボイドのFunc(A) { } int型のmain() { { のFunc(A())。 } 戻り 0 。 }
次のようにコードが一度だけのみコンストラクタとデストラクタが呼び出され、出力結果は、次のとおり
0x7ffeb5148d0f構築 0x7ffeb5148d0f破壊を
次のように最適化オプションがオフになっている-fno-Elideの-コンストラクタと結合G ++では、出力結果は、次のとおり
0x7ffc53c141ef構築 //主な機能は、Oパラメータ引数のコンストラクタに構成された可変なしで呼び出された 構築0x7ffc53c141eeコピー//関数のFuncを呼び出した後、引数はコピーコンストラクタA(のconst A&CP)を呼び出すためのパラメータと変数Oとして渡されます変数パラメータtを構築 0x7ffc53c141ee破壊デストラクタのA〜()を呼び出し、機能のFunc後に実行//、人生のパラメータ変数tの終わりを 破壊が0x7ffc53c141ef //効果O引数変数を残すために、主な機能を返すにドメイン、人生の終わり、そのデストラクタを呼び出す〜A()
ここではどのような最適化の挙動をシミュレートするためのC ++コードで:
ボイドのFunc(CONST A&A) { } int型のmain() { { のFunc(A())。 } 戻り 0 。 }
障害が発生した場合の最適化
(1)条件分岐に応じて、変数を返します
(2)リターンパラメータ変数
(3)グローバル変数を返します。
(4)複合データ型でメンバ変数を返します
(5)(この場合、代入演算子==オペレータを呼び出し)を構築し、良好な値を変数に代入される戻り
参照