4

私は「C++ のツアー」を経験してきましたが、Bjarne はコンストラクターのメンバー初期化で c++11 初期化子リスト機能を次のように使用します (中括弧を使用):

A a;
B b;
Foo(Bar bar):
  a{bar.a}, b{bar.b}
{}

ただし、これは c++11 より前ではコンパイルできません。古いメンバー初期化子リストとの違いは何ですか (丸括弧を使用):

Foo(Bar bar):
  a(bar.a), b(bar.b)
{}

では、どのような違いがあり、どちらを優先する必要があるのでしょうか?

4

3 に答える 3

9

違いは何ですか?

丸かっこは、非クラス型、またはかっこ内の引数の数に適したコンストラクターを持つ型に対してのみ機能します。

波括弧は、これらに加えて、集約 (structコンストラクターのない単純または配列型) にも機能します。したがって、次のように動作します。

struct {
    int a,b;
} aggregate;
int array[2];

Foo() : aggregate{1,2}, array{3,4} {}

initializer_list最後に、中括弧は、引数に一致するパラメーターを持つコンストラクターではなく、適切に型指定された を受け取るコンストラクターに一致します。例えば:

std::vector<int> v1;
std::vector<int> v2;

Foo() :
    v1(10,2),   // 10 elements with value 2
    v2{10,2}    // 2 elements with value 10,2
{}

いつ一方を優先する必要がありますか?

initializer_list初期化が集約または;ではなくコンストラクターを使用していることを明確にしたい場合は、丸括弧を使用してください。または、特定のコンストラクターの使用を強制します。

他の方法ではサポートされていない形式の初期化が必要な場合は、中括弧を優先してください。または、初期化で「正しいことをしたい」だけの場合。

両方が同じことを行う場合、選択は主に美的です。

于 2014-11-07T15:44:47.703 に答える
3

いくつかの本当に厄介なエッジ ケースで違いが生じる可能性があります。

std::vector<int> v{3, 2}; // constructs a vector containing [3, 2]
std::vector<int> u(3, 2); // constructs a vector containing [2, 2, 2]

vuが関数内の単なる変数であるか、初期化リストで初期化されたクラスのメンバーであるかに関係なく、これは当てはまります。

ただし、std::initializer_list<T>コンストラクターが同じ数の引数を取る通常のコンストラクターと重複する場合を除き、違いはありません。

于 2014-11-07T15:44:29.747 に答える
1

簡単な説明は次のとおりです。メンバー初期化子リストの表記は、他の場所で初期化された変数の表記と一致します。悲しいことに、コンストラクター呼び出しでの中括弧の使用に関連して、多少矛盾する 2 つの変更があるため、それが何をするかの説明はまったく簡単ではありません。

  1. 統一された初期化構文は、すべての構造で中括弧を使用するようにすることを目的としており、それがデフォルトの引数であるか、型にコンストラクターがまったくなく、直接初期化が使用されている場合でも、対応するコンストラクターを呼び出すだけです。
  2. 可変数の引数をサポートするために、中括弧を使用してstd::initializer_list<T>、余分な括弧/中括弧のペアなしで を提供できます。std::initializer_list<T>(適切な型の)を取るコンストラクTターがある場合、中括弧を使用するときにこのコンストラクターが使用されます。

別の言い方をすれば、コンストラクターがなく std::initializer_list<T>、他のユーザー定義のコンストラクターがある場合、括弧と中括弧の使用は同等です。それ以外の場合は、std::initializer_list<T>コンストラクターを呼び出します。...そして、初期化全体が実際には非常に複雑であるため、いくつかの詳細が欠けていると思います。

于 2014-11-07T15:41:21.003 に答える