web-dev-qa-db-ja.com

デフォルトのコンストラクターは組み込み型を初期化しますか?

デフォルトのコンストラクター(コンパイラーによって作成された)は組み込み型を初期化しますか?

162
Siggi

(コンパイラによって)暗黙的に定義されたクラスのデフォルトコンストラクターは、組み込み型のメンバーを初期化しません。

ただし、場合によっては、クラスのインスタンスの初期化を他の方法で実行できることに留意する必要があります。デフォルトのコンストラクターでも、コンストラクターでもありません。

たとえば、クラスCの構文C()は常にデフォルトコンストラクターを呼び出すという誤った信念が広まっています。しかし実際には、構文C()は、クラスインスタンスのいわゆるvalue-initializationを実行します。 ser-declaredの場合にのみ、デフォルトのコンストラクターを呼び出します。 (これはC++ 03にあります。C++ 98では-クラスが非PODの場合のみ)。クラスにユーザー宣言コンストラクターがない場合、C()はコンパイラー提供のデフォルトコンストラクターを呼び出しませんが、Cのコンストラクターをまったく含まない特別な種類の初期化を実行します。 。代わりに、クラスのすべてのメンバーを直接値で初期化します。組み込み型の場合、初期化はゼロになります。

たとえば、クラスにユーザー宣言のコンストラクターがない場合

class C { 
  int x;
};

コンパイラーは暗黙的に提供します。コンパイラが提供するコンストラクタは何もしません。つまり、C::xを初期化しません。

C c; // Compiler-provided default constructor is used
// Here `c.x` contains garbage

それにもかかわらず、以下の初期化will zero-initialize xは明示的な()初期化子を使用するため

C c = C(); // Does not use default constructor for `C()` part
           // Uses value-initialization feature instead
assert(c.x == 0);

C *pc = new C(); // Does not use default constructor for `C()` part
                 // Uses value-initialization feature instead
assert(pc->x == 0);

()初期化子の動作は、C++ 98とC++ 03の間でいくつかの点で異なりますが、この場合は異なります。上記のクラスCの場合、同じです:()初期化子は、C::xのゼロ初期化を実行します。

コンストラクターを使用せずに実行される初期化の別の例は、もちろん集約初期化です

C c = {}; // Does not use any `C` constructors at all. Same as C c{}; in C++11.
assert(c.x == 0);

C d{}; // C++11 style aggregate initialization.
assert(d.x == 0);
163
AnT

すべての実用的な目的のために-いいえ。


ただし、C++標準に技術的に準拠している実装の場合、答えはオブジェクトがPODかどうか、およびオブジェクトを初期化する方法に依存するということです。 C++標準によると:

MyNonPodClass instance1;//built in members will not be initialized
MyPodClass instance2;//built in members will be not be initialized
MyPodClass* instance3 = new MyPodClass;//built in members will not be initialized
MyPodClass* instance3 = new MyPodClass() ;//built in members will be zero initialized

ただし、現実の世界では、これは十分にサポートされていないため、使用しないでください。


標準の関連部分はセクション8.5.5および8.5.7です

18
JoeG

私はあなたが何を意味するのかよくわかりませんが、:

struct A { int x; };

int a; // a is initialized to 0
A b;   // b.x is initialized to 0

int main() {
    int c;         // c is not initialized
    int d = int(); // d is initialized to 0

    A e;           // e.x is not initialized
    A f = A();     // f.x is initialized to 0
}

私が「初期化されていない」と言う場合-あなたのコンパイラは一貫した値を与えるが、標準はそれを必要としないことに気付くかもしれません。

組み込み型が「実際に」デフォルトコンストラクターをどのように持っているかについて、私も含めて、多くの手を振っています。実際、デフォルトの初期化と値の初期化は標準で定義されている用語であり、個人的には毎回検索する必要があります。暗黙のデフォルトコンストラクタを持つために、標準ではクラスのみが定義されています。

17
Steve Jessop

前のスピーカーが述べたように-いいえ、彼らは初期化されていません。

これは実際には、最近のOSが新しく割り当てられたメモリ領域をゼロで埋める傾向があるため、本当に奇妙なエラーの原因になります。あなたがそれを期待するなら、それは初めて働くかもしれません。ただし、アプリケーションがdelete- ingおよびnew- ingオブジェクトを実行し続けると、遅かれ早かれ、ゼロが予想されるが、以前のオブジェクトからのゼロ以外の残りが置かれる状況になります。 。

では、なぜこれが、すべてのnew- edデータが新たに割り当てられないのですか?はい、ただし常にOSからではありません。 OSは、より大きなメモリチャンク(一度に4MBなど)で動作する傾向があるため、1ワード(ここでは3バイト)のすべての割り当てと割り当て解除は、すべてuyserspaceで処理されるため、ゼロ化されません。

PS。私は「傾向」を書きました。つまり、初めて成功に頼ることさえできません...

1
e8johan

標準に従って、初期化子リストで明示的に初期化しない限り、そうではありません

1
mukeshkumar