7

このコードフラグメントでは、実際にどのコンストラクターが呼び出されますか?

Vector v = getVector(); 

ベクターには、コピーコンストラクター、デフォルトコンストラクター、および代入演算子があります。

class Vector {
public:
    ...
    Vector();
    Vector(const Vector& other);
    Vector& operator=(const Vector& other);
};

getVectorは値で戻ります。

Vector getVector();

コードはC++03標準を使用します。

コードフラグメントは、デフォルトコンストラクターを呼び出してから代入演算子を呼び出すことになっているように見えますが、この宣言はコピーコンストラクターを使用する別の形式であると思われます。どちらが正しい?

4

4 に答える 4

8

初期化に=現れると、コピーコンストラクターを呼び出します。ただし、一般的な形式は、コピーコンストラクターを直接呼び出すこととまったく同じではありません。ステートメントT a = expr;では、exprがタイプTの場合、コピーコンストラクターが呼び出されます。exprがタイプTでない場合、可能であれば、最初に暗黙の変換が実行され、次にそれを引数としてコピーコンストラクターが呼び出されます。暗黙の変換が不可能な場合、コードの形式が正しくありません。

構造によってgetVector()は、コピーが最適化される場合があり、関数内で作成されたオブジェクトは、vに格納されるのと同じ物理オブジェクトです。

于 2012-03-31T15:49:21.897 に答える
2

表示しているコード以外で病理学的なことをしていないと仮定すると、宣言はコピー初期化であり、このルールの2番目の部分が適用されます。

13.3.1.3 Initialization by constructor [over.match.ctor]

1 When objects of class type are direct-initialized (8.5), or copy-initialized from an 
  expression of the same or a derived class type (8.5), overload resolution selects the
  constructor. For direct-initialization, the candidate functions are all the constructors
  of the class of the object being initialized. For copy-initialization, the candidate 
  functions are all the converting constructors (12.3.1) of that class. The argument 
  list is the expression-list within the parentheses of the initializer.

簡単なテストケースについては、Eli Benderskyの投稿(http://eli.thegreenplace.net/2003/07/23/variable-initialization-in-c/ )を参照してください。

于 2012-03-31T16:14:27.143 に答える
1

常にルールを覚えておいてください。
オブジェクトが作成され、同じ単一のステートメントで何らかの値が与えられている場合は常に、それが割り当てになることはありません。

さらに追加するには、

ケース1:

Vector v1;
Vector v(v1);

ケース2:

   Vector v = getVector(); 

上記の2つの形式では、ケース1直接初期化であり、ケース2はコピー初期化として知られています。

コピーの初期化はどのように機能しますか?
コピーの初期化は、暗黙の変換シーケンスを構築します。これは、の戻り値をgetVector()タイプのオブジェクトに変換しようとしますVector。次に、作成されたオブジェクトを初期化中のオブジェクトにコピーできるため、アクセス可能なコピーコンストラクターが必要です。

于 2012-03-31T16:29:12.280 に答える
0

この場合、コピーコンストラクターは実際には省略され(これをチェックしてください)、デフォルトのコンストラクターだけが呼び出されることになります。

編集:

ベンジャミンの答えによると、コンストラクターは時々省略されます。どういうわけか、コンストラクターを直接呼び出すときにそれを読みました。

于 2012-03-31T16:07:40.713 に答える