2

重複の可能性:
戻り値の最適化と戻り値の理解 - C++

Integerそれがメンバーであるいくつかのクラスにしましょうileft関数呼び出しにright引数として渡され、型Integer

ブルース・エッケルで与えられたように。

コード 1:

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

コード 2:

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

コード 1 は、一時的な整数オブジェクトを作成してそれを返すことを示しており、名前付きローカル変数を作成してそれを返すこととは異なります。これは一般的な誤解です。

コード 1 では (一時的なアプローチを返すと呼ばれます):
コンパイラは、作成しているオブジェクトを返す必要が他にないことを認識していますbuilding the object directly into the location of the outside return value。これには、単一の通常のコンストラクタ呼び出し (コピー コンストラクタなし) のみが必要であり、ローカル オブジェクトが作成されていないため、デストラクタは必要ありません。

コード 2 では 3 つのことが起こります:
a) コンストラクター呼び出しを含む tmp オブジェクトが作成されます
b) the copy-constructor copies the tmp to the location of the outside return value
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

4

1 に答える 1

2

コンパイラは、 pass-by-valueおよびreturn-by-valueのコピー コンストラクターを自由に最適化できます。私の推測では、適切なオプティマイザは両方の亜種に対して同じバイナリを生成します。

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

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 を外部の戻り値の場所にコピーする」というフレーズ。とてつもないことであり、時にはそれが起こらないことさえあります。

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

于 2012-01-04T08:31:13.007 に答える