web-dev-qa-db-ja.com

初期化リストの配列メンバーをゼロ初期化

すべてゼロに初期化したい配列メンバーを持つクラスがあります。

class X
{
private:
    int m_array[10];
};

ローカル変数の場合、ゼロで初期化する簡単な方法があります( ここ を参照):

int myArray[10] = {};

また、クラスメンバーm_array説明したように、デフォルト初期化intはランダムなガベージを残すだけなので、明らかに初期化する必要があります ここ

ただし、メンバー配列に対してこれを行うには2つの方法があります。

括弧付き:

public:
    X()
    : m_array()
    {}

ブレース付き:

public:
    X()
    : m_array{}
    {}

どちらも正しいですか? C++ 11の2つの間に違いはありますか?

25
ValarDohaeris

()でメンバーを初期化すると、値の初期化が実行されます。

{}を使用してデフォルトのコンストラクターでクラス型を初期化すると、値の初期化が実行されます。

{}を使用して他の集約タイプ(配列を含む)を初期化すると、リストの初期化が実行されます。これは、{}を使用して集約の各メンバーを初期化することと同じです。

{}を使用して参照タイプを初期化すると、{}から初期化された一時オブジェクトが作成され、その一時オブジェクトに参照がバインドされます。

{}を使用して他のタイプを初期化すると、値の初期化が実行されます。

したがって、ほとんどすべてのタイプで、{}からの初期化は、値の初期化と同じ結果になります。参照の配列を持つことはできないため、それらを例外にすることはできません。 mightデフォルトのコンストラクターなしで集約クラス型の配列を構築できますが、コンパイラーは正確な規則に同意していません。しかし、あなたの質問に戻るために、これらすべてのコーナーケースはあなたにとって本当に問題ではありません:あなたの特定の配列要素タイプに対して、それらは全く同じ効果を持っています。

16
user743382

初期化のタイプは少し面倒な場合がありますが、この場合は簡単です。ために:

public:
    X()
    : m_array()
    {}

括弧の間のexpression-listが空であるため、値の初期化が行われます。同様に:

public:
    X()
    : m_array{}
    {}

brace-init-listが空であるため、リストの初期化が行われ、その後に値の初期化が行われます。


より包括的な答えを与えるために、N4140の8.5を見ていきましょう。

  1. オブジェクトに初期化子が指定されていない場合、オブジェクトはデフォルトで初期化されます。自動または動的ストレージ期間を持つオブジェクトのストレージが取得されると、オブジェクトには不確定値があり、オブジェクトに対して初期化が実行されない場合、そのオブジェクトは、その値が置き換えられるまで不確定な値を保持します(5.17)。

これ不定値は、ガベージ値と呼ばれます。

  1. Tタイプのオブジェクトまたは参照をzero-initializeするには、次のことを意味します。

    — Tが配列型の場合、各要素はゼロで初期化されます

  2. タイプTのオブジェクトをvalue-initializeするには:

    — Tが(おそらくcv修飾された)クラス型である場合...オブジェクトはデフォルトで初期化されます。 ...

    — Tが配列型の場合、各要素は値で初期化されます。

    それ以外の場合、オブジェクトはゼロで初期化されます。

  3. 初期化子のセマンティクスは次のとおりです。 ... —イニシャライザが(括弧なし)braced-init-listの場合、オブジェクトまたは参照はリスト初期化されます(8.5.4 )。

    —初期化子が()の場合、オブジェクトは値で初期化されます。

これまでのところ、intはクラス型ではないため、値の初期化によって配列の各要素がゼロになることは明らかです。ただし、配列は集約であるため、リストの初期化と集約の初期化についてはまだ説明していません。

§8.5.4:

  1. Tタイプのオブジェクトまたは参照のリスト初期化は、次のように定義されます。

    — Tが集約の場合、集約の初期化が実行されます(8.5.1)。

そして§8.5.1に戻る:

  1. リスト内のinitializer-clausesが集合体のメンバーよりも少ない場合、明示的に初期化されていない各メンバーは、そのbrace-or-equal-initializerまたは、存在しない場合brace-or-equal-initializer、空の初期化リスト(8.5.4)から。

そして再び8.5.4で終わります:

  1. Tタイプのオブジェクトまたは参照のリスト初期化は、次のように定義されます。

    —それ以外の場合、初期化リストに要素がない場合、オブジェクトは値で初期化されます。

(ドラフト)標準をたどると息をのむことができるので、 cppreference をお勧めします。

関連リンク:

cppreference:

ドラフト標準:

13
user3920237