web-dev-qa-db-ja.com

C ++ 11で中括弧がある場合とない場合の初期化の違い

C++ 11では2つの方法で変数を初期化できます

1つ:

int abc = 7;

2:

int abc {7};

これら2つの方法の違いは何ですか?

コンパイラはそれらをどのように異なって扱うか、またはこれらのコードが実行される方法は?

29
techfun

短縮版

{..}による初期化はリスト初期化であり、変換を絞り込むことを禁止します。たとえば、LLONG_MAXlong long intの最大値であり、intがそれを表すことができない場合:

int x = LLONG_MAX;  // probably accepted with a warning
int x {LLONG_MAX};  // error

同様に:

long long y = /*something*/;

int x = y;  // accepted, maybe with a warning
int x {y};  // error

ロングバージョン

フォームの初期化

T x = a;

コピー初期化;いずれかの形式の初期化

T x(a);
T x{a};

直接初期化、[dcl.init]/15-16です。

[dcl.init]/14は、次のように述べています。

初期化の形式(括弧または=を使用)は一般に重要ではありませんが、初期化子または初期化されるエンティティがクラスタイプである場合は重要です。下記参照。

したがって、非クラス型の場合、初期化のformは重要ではありません。ただし、これら2つの直接初期化には違いがあります。

T x(a);  // 1
T x{a};  // 2

同様に、これら2つのコピー初期化の間:

T x = a;    // 1
T x = {a};  // 2

つまり、{..}のあるものはlist-initializationを使用します。 {..}braced-init-listと呼ばれます。

したがって、T x = a;T x {a};を比較すると、twoの違いがあります。コピーと直接初期化、および「非リスト」とリスト初期化です。他の人や上記の引用ですでに述べたように、非クラスタイプTの場合、copy-とdirect-initの間に違いはありません。ただし、list-initとnolist-initには違いがあります。つまり、比較することもできます

int x (a);
int x {a};

この場合のリストの初期化では、変換を絞り込むことが禁止されています。絞り込み変換は、[dcl.init.list]/7で次のように定義されています。

ナローイング変換は暗黙的な変換です

  • 浮動小数点型から整数型へ、または

  • long doubleからdoubleまたはfloatまで、またはdoubleからfloatまで。ただし、ソースが定数式であり、その後の実際の値は変換が表現できる値の範囲内である(正確に表現できない場合でも)、または

  • ソースが定数式であり、変換後の実際の値がターゲットタイプに適合し、元のタイプに変換して元の値を生成する場合を除いて、整数型またはスコープなしの列挙型から浮動小数点型へ、または

  • 整数型またはスコープなしの列挙型から、元の型のすべての値を表すことができない整数型へ。ただし、ソースが定数式であり、整数昇格後の値がターゲット型に適合する場合を除きます。

38
dyp

1つ目はコピーの初期化で、2つ目はリストの初期化です。

ただし、通常、コピーの初期化はあまり使用されません。なぜなら、ユーザー定義型のオブジェクトを渡すことによってそれを行っている場合、それはビットコピーを引き起こすだけであり、したがってユーザー定義クラスがポインターを使用する場合、意図した結果を生成しない可能性があるからです。

1
yuvi

intの場合、既存の応答は完了していますが、私は痛々しいほど、場合によっては、_()_と_{}_の初期化の間に他の違いがあることがわかりました。

キーワードは、_{}_が初期化子リストであるということです。

そのようなケースの1つは、countcharコピーを使用した_std::string_初期化です。

_std::string stars(5, '*')
_

starsを_*****_として初期化しますが、

_std::string stars{5, '*'}
_

std::string stars(char(5), '*')として読み取られ、スターを_*_として初期化します(前に非表示の文字が付きます)。

1
a.l.e