ここを見てください:GotW #1 : Variable Initialization。H. Sutter からの回答の詳細な説明です。
H. Sutter は上記で、変数の初期化の古いスタイルと新しいスタイルの一般的な意味で話しています。
以下は、開始トピックのコンテキストに従って、記事の簡単な概要を示しています。
このペア
double answer(42.0); // (1)
double answer{42}; // (2)
実際、次の初期化の例に似ています。
widget w(x); // (d)
widget w{x}; // (e)
これらは両方とも直接初期化です。ただし、構文{x}
によってinitializer_list
. widget
を受け取るコンストラクターがある場合initializer_list
、そのコンストラクターが優先されます。それ以外の場合、widget
任意の型を取るコンストラクターがあるx
場合 (おそらく変換あり)、そのコンストラクターが使用されます。
(2, e) を (1, d) よりも優れたものにする主な違いが 2 つあります。
- まず、構文 (2, e) は明確であり、「厄介な解析」を回避します。
x
が型名の場合、(1, d) は、x
スコープ内に名前が付けられた変数 (上記を参照) があっても関数宣言ですが、(2, e) は決して関数宣言ではありません。
第 2 に、構文 (2, e) はより安全です。なぜなら、それ以外の場合は一部の組み込み型で許可される縮小 (別名「非可逆」) 変換が許可されないためです。検討:
int i1( 12.345 ); // ok: toss .345, we didn't like it anyway
int i2{ 12.345 }; // error: would be lossy implicit narrowing
次のペア
ComplexNumber i(0,1); // (3)
std::vector<double> i{0,1}; // (4)
複雑なオブジェクトの初期化に関連付けられています。どちらもまったく同じように見えますが、2 番目のものは、次のような「厄介な解析」を回避するのに役立ちます。
ComplexNumber w( real(), img() ); // oops, vexing parse
それに加えて、この方法はコードをより明確にし ( を使用するinitializer_list
と、初期化であることがより明確になります)、さらに、場合によっては構文を緩和します。たとえば、次のようになります。
draw_rect({ origin, selection }); // C++11
Sutter ギルドラインは次のとおりです。or{ }
などの初期化を使用することを好みます。これは、より一貫性があり、より正確であり、古いスタイルの落とし穴について知る必要がまったくないためです。;のように、記号だけを表示したい単一引数の場合。そして; 中括弧を省略しても問題ありません。vector<int> v = { 1, 2, 3, 4 };
auto v = vector<int>{ 1, 2, 3, 4 };
=
int i = 42
auto x = anything
特別なコンストラクターの明示的な呼び出しに () 初期化を使用できます。