web-dev-qa-db-ja.com

初期化リストの利点

初期化リストを使用する利点について私が知っていることは、組み込みではないクラスメンバーを初期化するときに効率が上がることです。例えば、

Fred::Fred() : x_(whatever) { }

よりも好ましい

Fred::Fred() { x_ = whatever; }

xがカスタムクラスのオブジェクトである場合。それ以外は、一貫性を保つために、このスタイルは組み込みタイプでも使用されます。

これを行うことの最も一般的な利点は、パフォーマンスの向上です。式がメンバー変数x_と同じタイプである場合、式の結果はx_内で直接構築されます—コンパイラーはオブジェクトの個別のコピーを作成しません。

他のスタイルでは、式は別の一時オブジェクトを作成し、この一時オブジェクトはx_オブジェクトの代入演算子に渡されます。次に、その一時オブジェクトは;で破棄されます。それは非効率的です。

質問
初期化リストを使用すると、次の例で効率が向上しますか。利益はないと思います。最初のバージョンは文字列のコピーコンストラクターを呼び出し、他のバージョンは文字列の代入演算子を呼び出します(一時的なものは作成されません)。それは正しいですか?

class MyClass
{
public:
    MyClass(string n):name(n) { }
private:
    string name;
};

class MyClass
{
public:
    MyClass(string n)
    {
        name=n;
    }
private:
    string name;
};
40
Ankur

2番目のバージョンは文字列のデフォルトのctorを呼び出し、次に文字列のコピー割り当て演算子を呼び出します-cのコピーctorを直接呼び出す最初のバージョンと比較して(マイナーな)効率の低下が確実に発生する可能性があります(たとえば、文字列の実装によっては、役に立たない割り当て-その後、いくつかの小さな構造のリリース)。なぜ常に正しい方法を使用しないのですか?-)

33
Alex Martelli

Constデータメンバーを初期化する唯一の方法は初期化リストにあると思います

例えば。ヘッダー内:

class C
{
    C();
private:
    const int x;
    int y;
}

そして、cppファイル内:

C::C() :
    x( 10 ),
    y( 10 )
{
    x = 20; // fails
    y = 20;
}
15
pxb

これは、次のようなメンバーを初期化するための優れた方法です。

  • constです
  • デフォルトのコンストラクターがありません(プライベートです)
13
Maciek

以下は、初期化子リストを使用する場合のシナリオです。

  1. 非静的constデータメンバーの初期化用。
  2. 参照メンバーの初期化用。
  3. デフォルトのコンストラクターを持たないメンバーオブジェクトの初期化用。
  4. 基本クラスメンバーの初期化用。
  5. コンストラクターのパラメーター名がデータメンバーと同じ場合。
  6. パフォーマンス上の理由から。
11
Roy

コピーコンストラクタと代入演算子には明確な違いがあることに注意してください。

  • copy ctor constructs初期化情報を取得する場所として他のインスタンスを使用する新しいオブジェクト。
  • 代入演算子は、すでに完全に構​​築されている既存のオブジェクトを変更します(デフォルトのコンストラクターを使用するだけの場合でも)

したがって、2番目の例では、その時点までにnameを作成するための作業がすでに行われています。

 name=n;

が達成された。

ただし、(特にこの単純な例では)実行される作業が非常に小さく(おそらくstringオブジェクトの一部のデータメンバーをゼロにするだけ)、最適化されたビルドで作業が完全に最適化される可能性は十分にあります。ただし、可能な場合は常に初期化リストを使用することをお勧めします。

11
Michael Burr

初期化リストを介して コンストラクター委任 を実行することもできます。

2
Pranav Jain