2012-03-12 13 views
0

は、私は2つの関数AとB戻り値の最適化(RVO)Cに一時を用い++

関数AがオブジェクトXを返し、関数Bは、引数としてオブジェクトXを取得

を有していると言うことができます。例えば。

X A() { 
    X x; 
    return x; 
} 

void B(X x) { 
    write(x.data, x.size); 
} 

int main() { B(A()); } 

は、Xは、RVOを使用してBの一時的なとして一度だけ構築したり、私が移動セマンティクスを使用する必要があります。このオブジェクトです。

+1

答えが最も可能性の高いあなたのコンパイラに依存することになります印刷していないRVOで

 default constructed destructed 

を印刷します。特定のコンパイラを覚えていますか? –

答えて

2

コピーエリジョンを使用すると、Xは1回だけ作成されます。

コピーエリミッションが無効になっていても(例えば-fno-elide-constructorsをgccに渡しても)、ムーブコンストラクタは自動的に使用されます。

あなたはそれを自分で可視化することができます。

#include <cstdio> 

struct X 
{ 
    X() { printf("default constructed\n"); } 
    ~X() { printf("destructed\n"); } 
    X(const X&) { printf("copy constructed\n"); } 
    X(X&&) { printf("move constructed\n"); } 
}; 

X A() { 
    X x; 
    return x; 
} 

void B(X x) { 

} 

int main() { 
    B(A()); 
} 

RVOで、それはそれは

 
default constructed 
move constructed 
destructed 
move constructed 
destructed 
destructed 
3

コンパイラはがRVOを実行するために許可されているだけが、は、標準によってを義務はありません。そのため、使用するコンパイラやそのパラメータに応じて、コードを最適化するかどうかを決めることができます。

もう一つの問題は、関連する詳細情報が役立つことがあります:When should RVO kick-in?

+0

私はそれがC++ 11の要件だと思っていますが、そうでない場合でも、rvalue参照と移動セマンティクスを実装している普通のコンパイラはそれを持っていません。 –

+3

@CatPlusPlus:C++ 11はRVOを必要としません.RVOが使用されていない場合は、戻り値がコピーされるのではなく移動される必要があります。 –

+0

@MikeSeymour:ああ、十分に近いです。 –

0

私はあなたがちょうどあなたが興味を持っているものは何でもコンパイラ使用して、それをテストすることをお勧めします - (いくつかの副作用を持っているXのコピーコンストラクタを定義する、すなわち例えば印刷メッセージ)、あなたが与えたコードがコンパイラのためにあなたの好みの最適化設定でどのようになっているかを見てください。

1

おそらく同じオブジェクトになります(つまり、余分なコピーは作成されません)。これはRVOではありませんが、コピーエリートと呼ばれています。

引用はC++ 11からではなく、C++ 03:

12.2/2ここでは一時的なオブジェクト

、実装はXを構築するためにする一時的に使用する場合があります(2)Xのコピーコンストラクタを使ってf()に渡す。あるいは、引数を保持するために使用される領域にX(2)が構築されることがあります。 /.../

+1

RVOとコピーelisionは同じことです。 (または:RVOはコピーエリミッションの1つのインスタンスです。) –

+1

@CatPlusPlus RVOはコピーエリミッションのインスタンスですが、同じことにはなりません。 –

+0

さて、RVOとコピーelisionはどうやって違いますか? –

関連する問題