532
MyClass a1 {a};     // clearer and less error-prone than the other three
MyClass a2 = {a};
MyClass a3 = a;
MyClass a4(a);

なんで?

4

5 に答える 5

474

基本的に、Bjarne Stroustrup の「The C++ Programming Language 4th Edition」からコピーして貼り付けます。

リストの初期化では、ナローイングは許可されません (§iso.8.5.4)。あれは:

  • 整数は、その値を保持できない別の整数に変換できません。たとえば、char から int への変換は許可されていますが、int から char への変換は許可されていません。
  • 浮動小数点値は、その値を保持できない別の浮動小数点型に変換できません。たとえば、float から double は許可されますが、double から float は許可されません。
  • 浮動小数点値は整数型に変換できません。
  • 整数値は浮動小数点型に変換できません。

例:

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

結論

よほどの理由がない限り、代替手段よりも {} の初期化を優先してください。

于 2013-08-14T03:56:12.220 に答える
161

リストの初期化を使用する利点については、すでに優れた回答がありますが、私の個人的な経験則では、可能な限り中括弧を使用せず、代わりに概念的な意味に依存させます。

  • 作成しているオブジェクトが、コンストラクターで渡す値 (コンテナー、POD 構造体、アトミック、スマート ポインターなど) を概念的に保持している場合は、中かっこを使用しています。
  • コンストラクターが通常の関数呼び出しに似ている場合 (引数によってパラメーター化された多かれ少なかれ複雑な操作を実行する)、通常の関数呼び出し構文を使用しています。
  • デフォルトの初期化では、常に中括弧を使用します。
    1つには、そのようにして、オブジェクトが、たとえば、とにかく呼び出されるデフォルトコンストラクターを持つ「実際の」クラスであるか、組み込み/ PODタイプであるかに関係なく、オブジェクトが初期化されることを常に確信しています。次に、ほとんどの場合、最初のルールと一致します。デフォルトで初期化されたオブジェクトは「空の」オブジェクトを表すことが多いためです。

私の経験では、このルールセットは、デフォルトで中括弧を使用するよりもはるかに一貫して適用できますが、使用できない場合、または括弧を使用した「通常の」関数呼び出し構文とは異なる意味を持つ場合は、すべての例外を明示的に覚えておく必要があります。 (別のオーバーロードを呼び出します)。

たとえば、次のような標準のライブラリタイプにうまく適合します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
于 2016-05-14T15:24:43.633 に答える