標準およびthe C++の本によると、クラス型メンバーのデフォルトコンストラクターは、暗黙的に生成されたデフォルトコンストラクターによって呼び出されますが、組み込み型は初期化されません。ただし、このテストプログラムでは、ヒープ内のオブジェクトを割り当てるとき、または一時オブジェクトを使用するときに、予期しない結果が発生します。
#include<iostream>
struct Container
{
int n;
};
int main()
{
Container c;
std::cout << "[STACK] Num: " << c.n << std::endl;
Container *pc = new Container();
std::cout << "[HEAP] Num: " << pc->n << std::endl;
delete pc;
Container tc = Container();
std::cout << "[TEMP] Num: " << tc.n << std::endl;
}
私はこの出力を取得します:
[STACK] Num: -1079504552
[HEAP] Num: 0
[TEMP] Num: 0
これはコンパイラ固有の動作ですか?私はこれに頼るつもりはありませんが、特に3番目のケースで、なぜこれが発生するのか知りたいです。
予想される動作です。 「デフォルトの初期化」と「値の初期化」の2つの概念があります。初期化子について言及しない場合、オブジェクトは「デフォルトで初期化」されますが、言及すると、デフォルトのコンストラクターの()としても、オブジェクトは「値で初期化」されます。コンストラクターが定義されている場合、どちらの場合もデフォルトのコンストラクターを呼び出します。ただし、組み込み型の場合、「値の初期化」はメモリをゼロにしますが、「デフォルトの初期化」はそうではありません。
したがって、初期化するとき:
Type x;
デフォルトのコンストラクターが提供されている場合はそれを呼び出しますが、プリミティブ型は初期化されません。ただし、初期化子について言及する場合、たとえば.
Type x = {}; // only works for struct/class without constructor
Type x = Type();
Type x{}; // C++11 only
プリミティブ型(または構造体のプリミティブメンバー)はVALUEで初期化されます。
同様に:
struct X { int x; X(); };
コンストラクターを定義する場合
X::X() {}
xメンバーは初期化されませんが、コンストラクターを定義すると
X::X() : x() {}
vALUEで初期化されます。これはnew
にも当てはまります。
new int;
初期化されていないメモリを提供するはずですが、
new int();
ゼロに初期化されたメモリを提供するはずです。残念ながら、構文は次のとおりです。
Type x();
文法のあいまいさのために許可されておらず、
Type x = Type();
は、デフォルトのコンストラクターを呼び出し、その後にcopy-constructorを呼び出す必要があります(指定されていて、インライン化できない場合)。
C++ 11では、新しい構文が導入されています。
Type x{};
これは両方の場合に使用できます。それでも古い標準に固執している場合は、Boost.ValueInitializedがあるので、テンプレート引数のインスタンスを適切に初期化できます。
より詳細な議論は、例えばで見つけることができます。 Boost.ValueInitializedドキュメント内 。
簡単な答えは次のとおりです。空の括弧は 値の初期化 を実行します。
あなたが言う時 Container *pc = new Container;
代わりに、さまざまな動作が観察されます。