これについて同僚と話し合った後、私はいくつかの疑問を抱きました...
タイトルが示すように、組み込み型が不明な値ではなく0に初期化されると想定できるのはいつですか。
ルールはC++標準間で異なりますか?
これについて同僚と話し合った後、私はいくつかの疑問を抱きました...
タイトルが示すように、組み込み型が不明な値ではなく0に初期化されると想定できるのはいつですか。
ルールはC++標準間で異なりますか?
完全なルールは[dcl.init](C ++ 11)にあります。要約すると、宣言で初期化子が指定されていない場合、エンティティはいわゆるデフォルトで初期化されます。クラスタイプの場合、これはデフォルトのコンストラクターが呼び出されることを意味します。非クラスタイプの場合、これは初期化が実行されないことを意味します。
ただし、[dcl.init]§9には次のように記載されています。「静的ストレージ期間のすべてのオブジェクトは、他の初期化が行われる前に、プログラムの起動時にゼロで初期化されます。」
これは、非クラス型の静的期間変数(名前空間スコープ変数など)がゼロで初期化されることを意味します。非クラスタイプの他のオブジェクト(ローカル変数など)は初期化されません。
C++98とC++03の両方の標準によると:
3.6.2非ローカルオブジェクトの初期化、§1:
静的ストレージ期間(3.7.1)のオブジェクトは、他の初期化が行われる前にゼロ初期化(8.5)される必要があります。
3.7.1静的保存期間、§1:
動的ストレージ期間もローカルでもないすべてのオブジェクトには、静的ストレージ期間があります。
3.7.1静的保存期間、§3:
このキーワード
static
を使用して、静的ストレージ期間を持つローカル変数を宣言できます。
また、8.5イニシャライザー、§6:
静的ストレージ期間のすべてのオブジェクトは、他の初期化が行われる前に、プログラムの起動時にゼロで初期化される必要があります。
これは両方の規格で同じです。唯一の違いは、C++98の8.5§6の定式化です。
静的ストレージ期間のオブジェクトによって占有されているメモリは、他の初期化が行われる前に、プログラムの起動時にゼロで初期化される必要があります。
これが例です。ここでx
、y
およびは静的ストレージ期間を持っているため、標準では、プログラムの起動時に両方がゼロで初期化されることが保証されています。PODオブジェクトもありa
、b
同じ方法で宣言されているため、静的な保存期間があります。つまり、それらのメンバー(i
およびd
)もゼロで初期化されます。
struct POD {
int i;
double d;
};
int x;
POD a;
int foo() {
static int y;
return y;
}
int main() {
static POD b;
std::cout << "x = " << x << std::endl;
std::cout << "y = " << foo() << std::endl;
std::cout << "a.i = " << a.i << std::endl;
std::cout << "b.d = " << b.d << std::endl;
}
もちろん、この例の出力は次のようになります。
x = 0
y = 0
a.i = 0
b.d = 0
以前に回答した正確な質問に回答するのではなく、静的ストレージを備えたPODオブジェクトのみが自動的に0に初期化されるので、コンパイラにメンバーを初期化させるためのコードを提供しようとします。
struct POD {
int a;
double b; //...
};
// namespace level:
POD p;
void f() {
POD n1; // uninitialized
POD p1 = {};
POD p2 = POD();
POD* n2 = new POD; // uninitialized
POD* pp1 = new POD();
delete n2; delete pp1;
}
上記の例では、「初期化されていない」とマークされたものだけが開始されません。これは標準で義務付けられていることに関するものであることに注意してください。マイレージはコンパイラによって異なります。特に、VSにはいくつかの問題がT t = T();
ありT* p = new T()'
、いくつかのシナリオがあります(タイプT
がPODではないが、ユーザー提供のデフォルトコンストラクターがない場合、コンパイラーはPODサブオブジェクトの初期化に失敗します。
struct T {
std::string s;
int i;
};
void f() {
T t = T(); // t.i == 0 according to the standard
}
暗黙の型が0に初期化されるとは思いません。これは、デバッガー内で実行していて、デバッグヒープ/スタックを使用している場合に当てはまる場合があります。デバッガーの外部にいる場合、または_NO_DEBUG_HEAP = 1環境変数を使用してデバッグヒープを無効にする場合、またはそれ以外の場合は、ほとんどの場合、メモリが初期化されないことがわかります。
経験則として、この方法でプログラムする方が安全なので、変数を初期化します。
編集:Luchian Grigoreが指摘しているように、グローバル/名前空間スコープ変数は例外です。また、この初期化のために、初期化されていない変数チェックでは機能しないことがよくあります。