C++ コピー コンストラクター、一時ファイル、およびコピー セマンティクス
質問
このプログラムについて
#include <iostream>
using std::cout;
struct C
{
C() { cout << "Default C called!\n"; }
C(const C &rhs) { cout << "CC called!\n"; }
};
const C f()
{
cout << "Entered f()!\n";
return C();
}
int main()
{
C a = f();
C b = a;
return 0;
}
私が得る出力は次のとおりです:
Entered f()!
Default C called!
CC called!
以来 f()
値によって返される場合、一時的な値を返す必要があります。として T a = x;
は T a(x);
, を構築するためにコピー コンストラクターを呼び出すのではありませんか? a
, 、一時的に渡されたものを引数として使用しますか?
解決
f()
が値で返しているので、、それは一時的に返す必要があります。
T a = x;
がT a(x);
あるとして、それは渡された引数として一時的に、a
の建設のためのコピーコンストラクタを呼び出すことはないでしょうか。
戻り値の最適化を検索します。これがデフォルトでオンになっています。あなたはMSVCを使用してWindows上にある場合2005+あなたはこのをオフにし、所望の結果(またはGCCの/Od
)を取得するために-fno-elide-constructors
を使用することができます。また、MSVCのためにこのの記事参照してください。
の 12.8コピーするクラスは、の
オブジェクトの 15 の特定の基準が満たされた場合、 実装は省略することが許可されています クラスオブジェクトのコピーの構築、 でも、コピーコンストラクタ場合および/または オブジェクトのデストラクタは、側面を持っています 効果。このような場合には、 実装の扱い源と 省略コピー操作の対象 単に二つの異なる方法として、 同じオブジェクトを参照すると、 そのオブジェクトの破壊が発生した時に 後の2回の オブジェクトが持っているでしょう なしで破壊されて コピーのこのエリジオンoptimization.115 操作はに許可されています 以下の状況(であってもよいです 複数を排除するために結合 コピー):
- 内のでreturn文 クラスの戻り値の型を持つ関数、の 式は、Aの名前であるとき 非揮発性自動オブジェクト 同じCV-修飾されていないタイプ 関数の戻り値の型、コピー 操作はで省略することができます 自動オブジェクトを構築 直接、関数の戻り値に 値 - スローイン式に、とき オペランドはAの名前です。 不揮発性自動オブジェクト、 オペランドからのコピー操作 例外オブジェクト(15.1)を省略することができます 自動オブジェクトを構築することにより、 直接例外オブジェクトへの
- ときがある一時的なクラスオブジェクト 参照にバインドされていない(12.2) でクラスオブジェクトにコピーされます 同じCV-修飾されていないタイプ、コピー 操作はで省略することができます 一時オブジェクトを構築 直接のターゲットに 省略コピー
- とき 例外の例外宣言 ハンドラ(箇条15)は、オブジェクトを宣言します 同じタイプの(を除きます 例外として、CV-資格) オブジェクト(15.1)、コピー操作缶 処理することにより省略することが 別名として例外宣言 例外オブジェクトの意味であれば プログラムは除く変更されません コンストラクタの実行のためにと によって宣言されたオブジェクトのデストラクタ 例外宣言ます。
注:重点鉱山の
他のヒント
これはを戻り値の最適化(RVO)の機能コンパイラがサポートします。
の例です。のコピーコンストラクタのかもしれないを使用すると、値によって返されたときに呼び出されます。
この機能をオフにするGCCの使用の-fno-elide-constructors
オプションます。
と呼ばれていると思います 戻り値の最適化.
いつだと思います f()
戻り値 C
object オブジェクトは呼び出し側メソッドのスタック領域に割り当てられるため、初期化するためにコピーは必要ありません C a
. 。これはあなたの default C called
.
C b = a
これにより、コピー コンストラクターが発生するため、 CC called
.
ところで、Wiki の例はあなたのコードと非常によく似ています。