コンパイラが生成したデフォルトコンストラクタでは組み込み型メンバは初期化されない

C++Javaと違っていてはまりがちなところ。

C++ Programming Language Special Edition」10.4.2節 (p.243) に次のように書いてあります。

A compiler-generated default construcor implicitly calls the default constructors for a class' members of class type and bases.


つまり、デフォルトコンストラクタでは、メンバ変数の初期化は次のようになります。

  • クラス型のメンバに対してはデフォルトコンストラクタが呼ばれる
  • 組み込み型メンバは初期化されない


テストコード

#include <iostream>
using namespace std;

class Integer{
public:
  int i;
  Integer() : i(0) {};
};

class Integer2{
public:
  int i;
};

class Test{
public:
  int i;
  Integer I1;
  Integer2 I2;
};

int main(){

  Test obj; // Compiler-generated default constructor
  cout << "Test::i " << obj.i << endl;
  cout << "Test::I1::i " << obj.I1.i << endl;
  cout << "Test::I2::i " << obj.I2.i << endl;

}


出力(一例)

Test::i 1628880154
Test::I1::i 0
Test::I2::i 1628704768

  • obj.iはTestのデフォルトコンストラクタで初期化されないのでゴミの値が入っている
  • obj.I1はTestのデフォルトコンストラクタで初期化される
    • つまりI1のデフォルトコンストラクタが呼ばれて、I1.iは0で初期化される
  • obj.I2はTestのデフォルトコンストラクタで初期化される
    • つまりI2のデフォルトコンストラクタが呼ばれる
    • だが、I2のデフォルトコンストラクタはコンパイラが生成したものなので、I2.iは初期化されずゴミの値が入っている


この話は、"コンパイラが生成したデフォルトコンストラクタ"に限らずコンストラクタ全般で同じことのようですが、その根拠は見つけられていません。