30

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

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 つの違いはありますか?

4

3 に答える 3

18

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

値の初期化を実行するデフォルトのコンストラクターで任意のクラス型を初期化し{}ます。

で他の集約型 (配列を含む) を{}初期化すると、リストの初期化が実行され、集約の各メンバーを で初期化するのと同じになります{}

で任意の参照型を初期化すると、{}から初期化された一時オブジェクトが構築され、その一時オブジェクト{}への参照がバインドされます。

で他の型を初期化すると{}、値の初期化が実行されます。

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

于 2014-12-09T19:29:14.437 に答える
14

初期化の種類はちょっと面倒かもしれませんが、この場合は些細なことです。為に:

public:
    X()
    : m_array()
    {}

括弧の間の式リストが空であるため、値の初期化が発生します。同様に:

public:
    X()
    : m_array{}
    {}

ブレース初期化リストが空であるため、リストの初期化が行われ、続いて値の初期化が行われます。


より包括的な回答を得るために、N4140 の 8.5 を見てみましょう。

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

この不確定な値は、ガベージ値と呼ばれるものです。

  1. 型のオブジェクトまたは参照をゼロで初期化Tするとは、次のことを意味します。

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

  2. タイプのオブジェクトを値で初期化Tするとは、次のことを意味します。

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

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

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

  3. 初期化子のセマンティクスは次のとおりです。... — 初期化子が (括弧で囲まれていない) 波括弧初期化リストである場合、オブジェクトまたは参照はリスト初期化されます (8.5.4)。

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

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

§8.5.4:

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

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

§8.5.1 に戻ります。

  1. 集約内のメンバーよりもリスト内の初期化句が少ない場合、明示的に初期化されていない各メンバーは、そのブレースまたは等号初期化子から初期化されるか、またはブレースまたは等号初期化子 がない場合、空のイニシャライザ リスト (8.5.4) から。

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

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

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

(ドラフト) 標準をたどると息が詰まる可能性があるため、cppreferenceをお勧めします。

関連リンク:

cppリファレンス:

ドラフト標準:

于 2014-12-09T20:37:25.983 に答える
-1

括弧は C++98 で機能し、ゼロの初期化を要求しています。これが必要です。gcc 4.3で確認しました。編集: C++11 に関する誤った記述を削除しました。また、-std=c++11 を指定した clang 3.4 を使用して、空のブレースが空のリストの初期化を実行することも確認しました。

于 2014-12-09T15:46:48.820 に答える