すべてゼロに初期化したい配列メンバーを持つクラスがあります。
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つの間に違いはありますか?
()
でメンバーを初期化すると、値の初期化が実行されます。
{}
を使用してデフォルトのコンストラクターでクラス型を初期化すると、値の初期化が実行されます。
{}
を使用して他の集約タイプ(配列を含む)を初期化すると、リストの初期化が実行されます。これは、{}
を使用して集約の各メンバーを初期化することと同じです。
{}
を使用して参照タイプを初期化すると、{}
から初期化された一時オブジェクトが作成され、その一時オブジェクトに参照がバインドされます。
{}
を使用して他のタイプを初期化すると、値の初期化が実行されます。
したがって、ほとんどすべてのタイプで、{}
からの初期化は、値の初期化と同じ結果になります。参照の配列を持つことはできないため、それらを例外にすることはできません。 mightデフォルトのコンストラクターなしで集約クラス型の配列を構築できますが、コンパイラーは正確な規則に同意していません。しかし、あなたの質問に戻るために、これらすべてのコーナーケースはあなたにとって本当に問題ではありません:あなたの特定の配列要素タイプに対して、それらは全く同じ効果を持っています。
初期化のタイプは少し面倒な場合がありますが、この場合は簡単です。ために:
public:
X()
: m_array()
{}
括弧の間のexpression-listが空であるため、値の初期化が行われます。同様に:
public:
X()
: m_array{}
{}
brace-init-listが空であるため、リストの初期化が行われ、その後に値の初期化が行われます。
より包括的な答えを与えるために、N4140の8.5を見ていきましょう。
- オブジェクトに初期化子が指定されていない場合、オブジェクトはデフォルトで初期化されます。自動または動的ストレージ期間を持つオブジェクトのストレージが取得されると、オブジェクトには不確定値があり、オブジェクトに対して初期化が実行されない場合、そのオブジェクトは、その値が置き換えられるまで不確定な値を保持します(5.17)。
これ不定値は、ガベージ値と呼ばれます。
T
タイプのオブジェクトまたは参照をzero-initializeするには、次のことを意味します。— Tが配列型の場合、各要素はゼロで初期化されます
タイプ
T
のオブジェクトをvalue-initializeするには:— Tが(おそらくcv修飾された)クラス型である場合...オブジェクトはデフォルトで初期化されます。 ...
— Tが配列型の場合、各要素は値で初期化されます。
それ以外の場合、オブジェクトはゼロで初期化されます。
初期化子のセマンティクスは次のとおりです。 ... —イニシャライザが(括弧なし)braced-init-listの場合、オブジェクトまたは参照はリスト初期化されます(8.5.4 )。
—初期化子が()の場合、オブジェクトは値で初期化されます。
これまでのところ、int
はクラス型ではないため、値の初期化によって配列の各要素がゼロになることは明らかです。ただし、配列は集約であるため、リストの初期化と集約の初期化についてはまだ説明していません。
§8.5.4:
T
タイプのオブジェクトまたは参照のリスト初期化は、次のように定義されます。— Tが集約の場合、集約の初期化が実行されます(8.5.1)。
そして§8.5.1に戻る:
- リスト内のinitializer-clausesが集合体のメンバーよりも少ない場合、明示的に初期化されていない各メンバーは、そのbrace-or-equal-initializerまたは、存在しない場合brace-or-equal-initializer、空の初期化リスト(8.5.4)から。
そして再び8.5.4で終わります:
T
タイプのオブジェクトまたは参照のリスト初期化は、次のように定義されます。—それ以外の場合、初期化リストに要素がない場合、オブジェクトは値で初期化されます。
(ドラフト)標準をたどると息をのむことができるので、 cppreference をお勧めします。
cppreference:
ドラフト標準: