MyClass a1 {a}; // clearer and less error-prone than the other three
MyClass a2 = {a};
MyClass a3 = a;
MyClass a4(a);
なんで?
MyClass a1 {a}; // clearer and less error-prone than the other three
MyClass a2 = {a};
MyClass a3 = a;
MyClass a4(a);
なんで?
基本的に、Bjarne Stroustrup の「The C++ Programming Language 4th Edition」からコピーして貼り付けます。
リストの初期化では、ナローイングは許可されません (§iso.8.5.4)。あれは:
例:
void fun(double val, int val2) {
int x2 = val; // if val == 7.9, x2 becomes 7 (bad)
char c2 = val2; // if val2 == 1025, c2 becomes 1 (bad)
int x3 {val}; // error: possible truncation (good)
char c3 {val2}; // error: possible narrowing (good)
char c4 {24}; // OK: 24 can be represented exactly as a char (good)
char c5 {264}; // error (assuming 8-bit chars): 264 cannot be
// represented as a char (good)
int x4 {2.0}; // error: no double to int value conversion (good)
}
= が {} より優先される唯一の状況は、auto
キーワードを使用して初期化子によって決定された型を取得する場合です。
例:
auto z1 {99}; // z1 is an int
auto z2 = {99}; // z2 is std::initializer_list<int>
auto z3 = 99; // z3 is an int
よほどの理由がない限り、代替手段よりも {} の初期化を優先してください。
リストの初期化を使用する利点については、すでに優れた回答がありますが、私の個人的な経験則では、可能な限り中括弧を使用せず、代わりに概念的な意味に依存させます。
私の経験では、このルールセットは、デフォルトで中括弧を使用するよりもはるかに一貫して適用できますが、使用できない場合、または括弧を使用した「通常の」関数呼び出し構文とは異なる意味を持つ場合は、すべての例外を明示的に覚えておく必要があります。 (別のオーバーロードを呼び出します)。
たとえば、次のような標準のライブラリタイプにうまく適合しますstd::vector
。
vector<int> a{10,20}; //Curly braces -> fills the vector with the arguments
vector<int> b(10,20); //Parentheses -> uses arguments to parametrize some functionality,
vector<int> c(it1,it2); //like filling the vector with 10 integers or copying a range.
vector<int> d{}; //empty braces -> default constructs vector, which is equivalent
//to a vector that is filled with zero elements