デフォルトコンストラクタ
デフォルトコンストラクタ(default constructor)は実引数の指定が不要なコンストラクタのことです。仮引数が宣言されていないコンストラクタはデフォルトコンストラクタとなります。
struct T {
T() {} // デフォルトコンストラクタ
};
T t = T(); // デフォルトコンストラクタ`T::T()`が呼ばれる
実引数指定の省略が可能なコンストラクタはデフォルトコンストラクタとみなされます。
struct U {
U(int v = 0) {} // デフォルトコンストラクタとしても機能
};
U u = U(); // `U::U(0)`が呼ばれる
目次
デフォルトコンストラクタの初期化
実引数が指定されていない初期化式は、デフォルトコンストラクタを呼び出します。
/* いずれも、デフォルトコンストラクタ`T::T()`が呼ばれる */
T t;
T t();
T t{};
T t = T();
T t = T{};
T t = {};
T *t = new T();
fn({}); // T fn(T t) { return {}; }
デフォルトコンストラクタの宣言・定義
デフォルトコンストラクタはクラス名() {}
形式で宣言します。
struct T {
T() {} // デフォルトコンストラクタ
};
メンバ変数の初期化を行う際には、コンストラクター初期化子を用いてコンストラクタを定義する必要があります。
struct T {
int v;
T() : v(9) {} // コンストラクタ初期化子によるメンバ変数の初期化
};
assert( 9 == T().v ); // 成功
コンストラクタ側でメンバ変数の初期化を省略した場合、メンバの値は不定なものとなります。
struct T {
int v;
T() {}
};
assert( 0 == T().v ); // failed: 不定値により失敗の可能性あり
なおメンバ初期化子を用いることで、各メンバ変数側で個別にメンバ変数の初期化を行うことも可能です。
struct T {
int v = 0; // メンバ初期化子による初期化
T() {}
};
assert( 0 == T().v ); // 常に成功
ただし、C++11ではメンバ初期化子による初期化と初期化リストによる初期化との混在ができないという問題があります。C++14以降の標準規格ではこの問題が解消されています。
struct T { int a, b = 2; };
T x{1};
// error: no matching constructor for initialization of 'T'
// note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const T' for 1st argument
// note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'T' for 1st argument
// note: candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided
T y{1, 2};
// error: no matching constructor for initialization of 'T'
// note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided
// note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided
// note: candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 2 were provided
デフォルト引数とデフォルトコンストラクタ
なお、デフォルト引数の利用によって、実引数の指定が実質不要となるようなコンストラクタは、デフォルトコンストラクタとみなされます。
struct T {
T(int v = 0) {} // 変換コンストラクタでかつデフォルトコンストラクタ
// T(int v) {} // 変換コンストラクタ
};
// デフォルトコンストラクタ呼び出し: `T::T(0)`が呼ばれる
T t = T();
T u = {};
// 変換コンストラクタ呼び出し : `T::T(9)`が呼ばれる
T t = T(9);
T u = {9};
T v = 9;
関連
変換コンストラクタとは|詳細解説と処理コストについて
ムーブコンストラクタとは|ムーブセマンティクスやコンテナ高速化との関係