初期化子リストに含める必要のないクラスメンバー変数を初期化子リストに入れることに何か利点はありますか?例:
class Foo
{
public:
Foo() {}
};
class Bar
{
public:
Bar() : _foo() {}
private:
Foo _foo;
};
この場合、コンパイラは何か特別なことをしますか?
初期化子リストに含める必要のないクラスメンバー変数を初期化子リストに入れることに何か利点はありますか?例:
class Foo
{
public:
Foo() {}
};
class Bar
{
public:
Bar() : _foo() {}
private:
Foo _foo;
};
この場合、コンパイラは何か特別なことをしますか?
この場合、違いはありません。
しかし、そうすることは有用です。
多数のメンバーがある場合、すべてのメンバーではなく一部のメンバーがリストに含まれていると、混乱が生じる可能性があります。また、初期化の順序を頭の中で強化します (順序はクラスでの宣言の順序によって定義されますが、すべてのメンバー変数が互いに並んで宣言されているわけではない大きなクラスでこの順序を視覚化すると便利です)。
注: インターナライザー リストでそれらを間違った順序で配置した場合、これは通常、ほとんどのコンパイラで単なる警告です (警告をエラーとしてコンパイルする場合を除きます (そうするべきです))。
本当の危険は、POD メンバーとコンパイラー生成コンストラクターを持つクラスにあります。
class NewFoo
{
int x;
int y;
};
// Version 1:
class Bar1
{
NewFoo f;
};
// Version 2:
class Bar2
{
NewFoo f;
public:
Bar2() // f not in list.
{}
};
// Version 3:
class Bar3
{
NewFoo f;
public:
Bar3()
: f()
{}
};
int main()
{
Bar1 b1a; // x and y not initialized.
Bar1 b1b = Bar1(); // x and y zero initialized.
Bar2 b2a; // x and y not initialized.
Bar2 b2b = Bar2(); // x and y not initialized.
Bar3 b3a; // x and y zero initialized.
Bar3 b3b = Bar3(); // x and y zero initialized.
}
初期化子リストは、コンストラクターでメンバーを初期化するための推奨される方法です。これは、参照メンバーと定数メンバーを初期化する唯一の方法です。
また、初期化子リストを使用することで、初期化される前に変数を誤って使用する可能性を減らします。これは、初期化せずに変数を定義しないというより大きな哲学の一部です。
使用されているコンストラクターの初期化リストに記載されていないメンバーは、デフォルトで初期化されます。これはFoo
、デフォルトのコンストラクターが呼び出されることを意味します。
明示的なデフォルト コンストラクターをまったく指定Bar() : _foo() { }
しない場合との違い(つまり、お使いのバージョンには単純なデフォルト コンストラクターがないということです。したがって、コンストラクターを完全に省略した場合とは値が異なりますが、それ以外の動作は同じです。 .Bar
Bar() = default
std::is_trivially_constructible<Bar>::value
いいえ、この場合は何も変わりません。これを行うことにメリットはありません。