C ++では、ゼロ、デフォルト、値の初期化というフレーズは何を意味していますか?


188

C ++での次のフレーズの意味は何ですか。

  • ゼロ初期化、

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

  • 値の初期化

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


1
これは(ただし、同一ではない)stackoverflow.com/questions/620137/…に
Steve Jessop

20
もっとあります!初期化の完全なリスト:値、直接、コピー、リスト(C ++ 11新しいイントロ)、集約、参照、ゼロ、定数、デフォルト。en.cppreference.com/w/cpp/language/initializationは、それらすべてを例とともにリストします:)
legends2k

回答:


64

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

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

答えの要点は:

new演算子によって返されるメモリが初期化されることもあれば、更新する型がPODであるか、それがPODメンバーを含み、コンパイラー生成のデフォルトコンストラクターを使用しているクラスであるかによって異なる場合もあります。 。

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

控えめに言っても、それはかなり複雑であり、さまざまな方法が実行されるタイミングは微妙です。

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;
}

1
それはにとって重要でintはありませんがm()、3行目の値はmを初期化します。に変更int m;する場合は重要ですB m;。:)
Johannes Schaub-litb 2009年

右- AC、この例で使用されていない(彼らは他のリンクの答えから引き継がれています)。C ++ 98とC ++ 03 は、方法AC構造を説明するときに異なる用語を使用していますが、結果は両方の標準で同じです。struct B結果が異なるだけです。
マイケルバー

1
つまり、Cをstruct C { C() : m() {}; ~C(); B m; };に変更すると、m.m0になります。ただし、mC ++ 03のようにdefault-initialise を実行するとm.m、C ++ 98のように初期化されません。
Johannes Schaub-litb

1
この機能のMSVCの取り扱いに関するその他の興味深いコメント:stackoverflow.com/questions/3931312/...
nobar

タイプをローカル変数として、つまりスタックで宣言するときに、どの初期化が行われますか?
アンドレ・Puel

87

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非修飾バージョンが使用されます。


17
これはC ++ 11の場合は古くなっている可能性があります。cppreference.comは、デフォルトの初期化でメンバーをゼロ初期化しないと述べています(値の初期化のみが行います)。
Alexei Sholik 2013

3
@androidは重要なポイントを提起しますが、これは他の場所では回答されていないので、新しい質問をしました。 stackoverflow.com/questions/22233148/…–
エイドリアンマッカーシー、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.