205

次のフレーズはC++で何を意味しますか?

  • ゼロ初期化、

  • デフォルト-初期化、および

  • 値の初期化

C ++開発者はそれらについて何を知っておくべきですか?

4

2 に答える 2

91

C++03 標準 8.5/5:

T 型のオブジェクトをゼロで初期化
するとは、次のことを意味します。 — T がスカラー型 (3.9) の場合、オブジェクトは T に変換された 0 (ゼロ) の値に設定されます。
— T が非共用体クラス型の場合、各非静的データ メンバーと各基本クラス サブオブジェクトはゼロで初期化されます。
— T が共用体型の場合、オブジェクトの最初の名前付きデータ メンバーはゼロで初期化されます。
— T が配列型の場合、各要素はゼロで初期化されます。
— T が参照型の場合、初期化は実行されません。

T 型のオブジェクトをデフォルトで初期化
するとは、次のことを意味します。 — T が非 POD クラス型 (第 9 節) である場合、T のデフォルト コンストラクターが呼び出されます (T にアクセス可能なデフォルト コンストラクターがない場合、初期化は不適切な形式です)。
— T が配列型の場合、各要素はデフォルトで初期化されます。
— それ以外の場合、オブジェクトはゼロで初期化されます。

T 型のオブジェクトを値で初期化
するとは、次のことを意味します。 — T がユーザー宣言コンストラクタ (12.1) を持つクラス型 (第 9 節) である場合、T のデフォルト コンストラクタが呼び出されます (T の場合、初期化の形式が正しくありません)。アクセス可能なデフォルト コンストラクターがありません);
— T が、ユーザーが宣言したコンストラクターを持たない非共用体クラス型である場合、T のすべての非静的データ メンバーと基底クラス コンポーネントは値で初期化されます。
— T が配列型の場合、各要素は値で初期化されます。
— それ以外の場合、オブジェクトはゼロで初期化されます

参照型のエンティティのデフォルトの初期化または値の初期化を呼び出すプログラムの形式が正しくありません。T が cv 修飾された型である場合、ゼロ初期化、デフォルト初期化、および値初期化のこれらの定義には、T の cv 修飾されていないバージョンが使用されます。

于 2009-10-23T13:20:55.977 に答える
66

認識すべきことの 1 つは、「値の初期化」が C++ 2003 標準で新しく追加されたことです。元の 1998 標準には存在しません (明確化以上の唯一の違いであると思います)。標準から直接の定義については、Kirill V. Lyadvinskyの回答を参照してください。

operator newこれらのタイプの初期化の異なる動作と、それらがいつ開始されるか (およびそれらが c++98 から C++03 に異なる場合) の詳細については、動作に関するこの以前の回答を参照してください。

答えの主なポイントは次のとおりです。

new 演算子によって返されるメモリが初期化されることもあれば、新しい型が POD であるかどうか、または POD メンバーを含み、コンパイラによって生成された既定のコンストラクターを使用しているクラスであるかどうかによって、初期化されないこともあります。 .

  • C++1998 では、ゼロとデフォルトの 2 種類の初期化があります。
  • C++2003 では、3 番目のタイプの初期化である値の初期化が追加されました。

控えめに言っても、それはかなり複雑であり、さまざまな方法が作動するときは微妙です。

確かに注意すべきことの 1 つは、VS 2008 (VC 9 または cl.exe バージョン 15.x) であっても、MSVC は C++98 の規則に従っているということです。

次のスニペットは、MSVC と Digital Mars が C++98 の規則に従っているのに対し、GCC 3.4.5 と Comeau は C++03 の規則に従っていることを示しています。

#include <cstdio>
#include <cstring>
#include <new>

struct A { int m; }; // POD
struct B { ~B(); int m; }; // non-POD, compiler generated default ctor
struct C { C() : m() {}; ~C(); int m; }; // non-POD, default-initialising m

int main()
{
    char buf[sizeof(B)];
    std::memset( buf, 0x5a, sizeof( buf));

    // use placement new on the memset'ed buffer to make sure 
    //  if we see a zero result it's due to an explicit 
    //  value initialization
    B* pB = new(buf) B();   //C++98 rules - pB->m is uninitialized
                            //C++03 rules - pB->m is set to 0
    std::printf( "m  is %d\n", pB->m);
    return 0;
}
于 2009-10-23T13:48:46.657 に答える