1

重複の可能性:
コンストラクターでのフィールドの初期化 - 初期化リストとコンストラクター本体

私が参加した講義で、講師はデフォルト以外のクラス コンストラクターについて C++ で簡単に説明しました。彼は、あるバージョンが他のバージョンよりも優れていると具体的に述べました。彼は次の 2 つの例を示しました。

Point::Point(double x, double y, double z)
: x_(x), y_(y), z_(z)
{}

Point::Point(double x, double y, double z)
{ x_= x; y_= y; z_= z; }

彼は、最初の例 (括弧を使用) がコンストラクターを記述するための推奨される方法であると述べました。

私の質問は次のとおりです:違いは何ですか?なぜそれが重要なのですか? 前者が後者より優れている点は何ですか。

4

3 に答える 3

3

その理由は、最初のコードは代入ではなく、初期化であり、2 番目のコードは実際にはこれと同じだからです。

Point::Point(double x, double y, double z)
: x_(), y_(), z_()
{ x_= x; y_= y; z_= z; }

つまり、すべてのメンバーは、割り当てられる前にここでデフォルトで初期化されます。それらの型にデフォルトのコンストラクターがない場合、それは機能しません。例えば:

class Foo {
    Foo(); // Private, undefined constructor
public:
    Foo(int) { }
};

class Bar {
    int& i;
    Foo f;

public:
    Bar() { i = 0; f = Foo(0); }
};

Barのコンストラクタは、 のデフォルト コンストラクタfと の初期化子の存在に依存しているため、このコードは機能しませんi。どちらも存在しません。

ただし、すべてのメンバーがデフォルトで構築可能または初期化可能である場合でも、コンストラクターでの代入ではなく、初期化リストでそれらを初期化することをお勧めします。場合によっては有料)。

于 2012-12-29T12:40:18.593 に答える
2

最初は、コンストラクタ本体が入力される前にメンバーをコピー構築します。注: これは、C++ でコンストラクター初期化子リストと呼ばれるものの、より大きな主題の一部です。特定のメンバー変数の型を初期化子リストで表すことが 必須です。その中には、参照メンバー、デフォルト以外の構成を持つメンバー (つまり、コンストラクターにパラメーターが必要)、および const メンバーがあります。質問で提示された場合の使用法は、デフォルト構築とそれに続く本体内割り当てではなく、コピー構築を呼び出すことです...

2 番目のデフォルトは、コンストラクター本体が入力される前にメンバーを構築し、本体内でそれらの値を割り当てます。これは、デフォルトの構築をサポートするメンバーに対してのみ実行可能です。

2 つのうち、特に高価なデフォルトの初期化がある複雑なデータ型の場合は、最初の方法が一般的に好まれます。この初期化は、これから行われる割り当てのために、部分的または完全に無駄になる可能性があります。一般に、それを先取りして、代わりにコピー構築を使用することをお勧めします。注:すべての組み込みデータ型 ( intfloat、ポインターなど) は、コピー構築をサポートしています。

于 2012-12-29T12:39:18.570 に答える
0

2 番目の方法は、デフォルトの構築を実行してから代入を実行します。

デフォルトのコンストラクターが利用できない場合、それは機能しません。

また、最初のメソッドは明示的なコンストラクターを呼び出すことができますが、2 番目のメソッドは呼び出しません。

于 2012-12-29T12:40:33.583 に答える