35

標準と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番目のケースで、なぜこれが発生するのか知りたいです。

4

2 に答える 2

50

予想される動作です。「デフォルトの初期化」と「値の初期化」の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ドキュメントなどにあります。

于 2011-02-08T12:19:13.513 に答える
18

簡単な答えは次のとおりです。空の括弧は値の初期化を実行します。

代わりに言うときContainer *pc = new Container;、あなたは異なる行動を観察するでしょう。

于 2011-02-08T12:19:40.730 に答える