まず、実際には 1 つのものの 2 つのバリエーションがあります。
T x = { 1, 2, 3 };
T x{1, 2, 3};
これら 2 つは実際には同じ初期化を行っていますが、コンストラクターを選択した場合に最初のものが無効になるという例外がありますexplicit
。それ以外は同一です。1 つ目は「コピー リスト初期化」と呼ばれ、2 つ目は「直接リスト初期化」と呼ばれます。
概念は、 を含むフォームが=
「複合値」 (3 つの int で構成される値) を割り当てているということです。そしてx
、その値で初期化します。このような初期化では、非 explicit
コンストラクターのみを許可する必要があります。x{1, 2, 3}
(等号なし)の概念は、変数を3 つの値で初期化することです。概念的には複合値ではなく、たまたま一度に 3 つの個別の値を指定することです。その用語の最も一般的な意味での「コンストラクター呼び出し」と言えます。
あなたが示した他の初期化は、実際には上記の2つとはまったく異なるものです:
T x({1, 2, 3});
T
withのコンストラクターを{1, 2, 3}
引数として呼び出すだけです。が配列である場合の配列の初期化や、 が集約構造体/クラスであるT
場合の構造体メンバーの初期化など、手の込んだことは一切行いません。がクラスでないT
場合、その宣言は無効です。T
しかし、T
たまたまコピー コンストラクターまたはムーブ コンストラクターがある場合は、そのコンストラクターを使用してT
、コピー リストの初期化によって一時的なコンストラクターを構築し、コピー/ムーブ コンストラクター参照パラメーターをその一時的なパラメーターにバインドできます。実際のコードでは、その形式はあまり必要ないと思います。
これはすべて、イニシャライザ リストの委員会提案書に記録されています。この場合、Initializer Lists — Alternative Mechanism and Rationaleのセクション「プログラマーの初期化の種類」を参照してください。
コピー初期化と直接初期化の違いを認識している熟練したプログラマーが、前者は後者よりも効率が悪いと誤って考えることがよくあります。(実際には、両方の初期化が理にかなっている場合、どちらも同じように効率的です。)
対照的に、これらのことを異なる用語で考える方がより有用であることがわかります。
- コンストラクターの呼び出しによる構築 (「ctor-call」)
- 値を転送して構築する (「変換」)
(たまたま、前者は「直接初期化」に対応し、後者は「コピー初期化」に対応しますが、標準の用語はプログラマーの役に立ちません。)
後で、彼らは見つけます
{ ... }
inを扱うので注意してください。
X x = { ... };
単一の値として、それはと同等ではありません
X x{ ... };
ここで、{ ... }
はコンストラクター呼び出しの引数リストです (N2531 とは異なるため強調します)。
C++0x FDIS に記載されている規則は、その文書に示されているものとは少し異なりますが、その文書に示されている理論的根拠は C++0x FDIS に保持され、実装されています。