2012-01-04 9 views
2

可能性の重複:
Understanding return value optimization and returning temporaries - C++ステップ

はそれがメンバーだとしてIntegeriといくつかのクラスになりましょう。 leftrightは、引数として関数呼び出しに渡され、タイプはInteger

であり、現在はBruce Eckelに与えられています。

コード1:

return Integer(left.i+right.i); 

コード2:

Integer tmp(left.i+right.i); 
return tmp; 

コード1は、一時的な整数オブジェクトを作成し、それを返すと言うと、それは、名前のローカル変数を作成し、それを返すと異なっています一般的な誤解です。コード1(一時的なアプローチを返すと呼ばれる)で


コンパイラは、あなたはit.Theコンパイラはbuilding the object directly into the location of the outside return valueによってこの利点を取り戻すために、次に作成のオブジェクトに他の必要性を持っていないことを知っています。これには、通常のコンストラクタ呼び出し(コピーコンストラクタなし)が1つだけ必要であり、ローカルオブジェクトが作成されていないためデストラクタは必要ありません。

ながらコード2に起こるのだろう3つの事:そのコンストラクタ呼び出し
B)the copy-constructor copies the tmp to the location of the outside return value含む
a)はTMPオブジェクトを作成しています。
c)デストラクタはスコープの終わりにtmpのために呼び出されます。

コード1では、これはどういう意味ですか?building the object directly into the location of the outside return value
なぜコピーコンストラクタはコード1で呼び出されませんか?

また、コード2のステップbは何をしているのか分かりませんでしたか?すなわちthe copy-constructor copies the tmp to the location of the outside return value

+0

「整数」はJavaに属します。 – iammilind

+0

ここで定義されていて(コードは表示されていない)、1つのintメンバーiとrest関数を持っているものとします。 –

+2

良いコンパイラは、両方のケースで同じアセンブリコードを作成します。 – littleadv

答えて

2

コンパイラは、値渡しリターンバイ値のためのコピーコンストラクタを最適化して自由です。私の推測では、まともなオプティマイザは両方のバリアントで同じバイナリを生成するということです。

コードの最適化されたバージョン:

A foo() 
{ 
    A temp; 
00401000 mov   ecx,dword ptr [A::x (40337Ch)] 
00401006 mov   dword ptr [eax],ecx 
00401008 add   ecx,1 
0040100B mov   dword ptr [A::x (40337Ch)],ecx 
    return temp; 
} 

だから、あなたが見るには、コピーコンストラクタは、それが影響観察された行動をするように、私のバージョンでは、それは、coutがあっても、かかわらず、呼び出されません。最適化なし

A foo() 
{ 
004113C0 push  ebp 
004113C1 mov   ebp,esp 
004113C3 sub   esp,0CCh 
004113C9 push  ebx 
004113CA push  esi 
004113CB push  edi 
004113CC lea   edi,[ebp-0CCh] 
004113D2 mov   ecx,33h 
004113D7 mov   eax,0CCCCCCCCh 
004113DC rep stos dword ptr es:[edi] 
    A temp; 
004113DE lea   ecx,[temp] 
004113E1 call  A::A (4110E6h) 
    return temp; 
004113E6 lea   eax,[temp] 
004113E9 push  eax 
004113EA mov   ecx,dword ptr [ebp+8] 

/// copy constructor called on next line: 

004113ED call  A::A (411177h) 
004113F2 mov   eax,dword ptr [ebp+8] 
} 

フレーズ「b)のコピーコンストラクタコピーTMP外の戻り値の場所へ。」遠くに突き出ている、時にはそれも起こらない。

これから覚えておくべきことは、コピーコンストラクタが呼び出されることに頼るべきではないということです。

+0

完全に合理的な答えは、 downvoted。 – littleadv

+0

@ littadadvおそらく質問に完全に答えなかったでしょう。それにもかかわらず、私はもう少し説明するように編集しました。 –