Есть ли какая-то польза от помещения переменной члена класса в список инициализаторов, который не обязательно должен быть в списке инициализаторов? Пример:
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
будет отличаться от того, если вы вообще не использовали конструктор, хотя в остальном поведение будет таким же.
Нет, в этом случае ничего другого не делается. Я не вижу никакой пользы от этого.