web-dev-qa-db-ja.com

コピーコンストラクターを明示的に呼び出すことはできますか?

コピーコンストラクターの仕組みについて少し混乱しています。私が間違っている場合は私を訂正してください:

メソッドがオブジェクトへの参照をパラメーターとして受け取り、クラスがコピーコンストラクターを定義する場合、クラスはコンストラクターを使用してそれ自体のコピーを作成し、元のオブジェクトへの参照の代わりに関数に渡されますか?

さらに、1つは呼び出すことができます

Object * obj = new Object(&anotherObject);

anotherObjectのコピーを作成するには?

18
Alex

いいえ、関数が参照を取る場合:

void f1( Object & o );   // call by reference

その後、コピーは作成されません。関数が値を取る場合:

void f2( Object o );   // call by value

次に、コピーコンストラクターを使用してコンパイラーによってコピーが作成されます。

そして、はい、あなたが言うとき:

Object * obj = new Object(anotherObject);   // not &anotherObject

コピーコンストラクターは明示的に使用されます(anotherObjectがObject型であると仮定します)。ただし、ここでのnewの使用には魔法はありませんが、この場合は次のようになります。

Object obj2(anotherObject);

コピーコンストラクタも使用されます。

27
anon

メソッドがオブジェクトへの参照をパラメーターとして受け取る場合、コピーコンストラクターは呼び出されません。その場合、コピーコンストラクター自体を呼び出すと、無限ループが発生します(引数として参照を受け取るため)。

その行は、コピーコンストラクターを呼び出す有効な方法ではありません。ポインタではなく、引数として参照を想定しています。

7
Mehrdad Afshari

ここでは、メソッド呼び出しを行っているという事実は重要ではありません。関数呼び出し中の参照パラメーターの初期化は、スタンドアロンの参照初期化と同じであり、同じルールによって管理されます。

参照の初期化のルールは少し複雑ですが、重要なのは、初期化子が左辺値(この場合はメソッド呼び出しの引数)であり、参照のタイプが初期化子のタイプと同じである場合(つまり、パラメータのタイプが引数のタイプと同じである場合)、参照は直接バインドされます。つまりコピーは作成されません。

Object a; // class type
Object &r = a; // no copying
const Object &cr = a; // no copying

これらの要件が満たされていない場合(たとえば、初期化子が右辺値である場合など)、すべてが異なります。場合によっては、コピーが行われる可能性があります。例えば

const Object &tr = Object();

コンパイラは次のように解釈できます

const Object &tr = Object(Object(Object(Object())));

実装に依存する有限数のコピーを使用します。もちろん、効率上の理由から、コンパイラーは通常、コピーが許可されている場合でも、不要なコピーを作成しないようにしています。

コンパイラのコピー動作の有効性についてしばしば議論を巻き起こす典型的な例は、次のような式での参照の初期化です。

Object a;
const Object &r = <some condition> ? a : Object();

C++参照セマンティクスに精通している人は、上記のような式が、参照の初期化中に不要なコピーを実行するための標準的なアクセス許可の背後にある理論的根拠である可能性が高いことを理解します。

3
AnT

どちらの場合もありません。最初のケースでは、そのオブジェクト自体への参照が渡され、コピーは作成されません。 2番目のケースでは、objectのコンストラクターへのポインターを渡しているため、コピーは作成されません。したがって、オブジェクトにはobject(anotherClass*)のようなコンストラクター(コピーコンストラクターではない)が必要です。

1
Naveen

コピーコンストラクタは、参照によるではなく値によるを渡すときにのみ呼び出されます。参照により、コピーは必要ありません(これは参照の目的の一部です!)ので、コピーコンストラクターは呼び出されません。

1
zaharpopov

はい、次のように新しい配置を使用します。

Object dstObject;
new(&dstObject) Object(&anotherObject);
0
HaPpY