C ++コンパイラの最適化技術:RVO、NRVO省略コピー

対と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)
        。AA(); 
    } 

    戻り 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)
        。AA(); 
    } 

    戻り 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)(この場合、代入演算子==オペレータを呼び出し)を構築し、良好な値を変数に代入される戻り

 

参照

戻り値の最適化 

コピーの省略と戻り値の最適化とは何ですか?

コピーの省略(ウィキ)

C ++という名前の戻り値の最適化(NRVO)

 

おすすめ

転載: www.cnblogs.com/kekec/p/11303391.html