Строительство - довольно сложная тема на C++. Простой ответ Это зависит от модели. Игнорируется ли Foo или нет, зависит от определения самого Foo. О втором вопросе: как заставить Bar инициализировать Foo: списки инициализации - ответ.
Хотя общий консенсус в том, что Foo будет инициализирован по умолчанию неявным конструктором по умолчанию (сгенерирован компилятором), который не должен содержать true.
Если Foo не имеет пользовательского конструктора по умолчанию, то Foo будет неинициализирован. Чтобы быть более точными: каждый член Bar или Foo не хватает определенного пользователя конструктора по умолчанию будет инициализирован компилятор генерируется конструктор по умолчанию Bar:
class Foo {
int x;
public:
void dump() { std::cout << x << std::endl; }
void set() { x = 5; }
};
class Bar {
Foo x;
public:
void dump() { x.dump(); }
void set() { x.set(); }
};
class Bar2
{
Foo x;
public:
Bar2() : Foo() {}
void dump() { x.dump(); }
void set() { x.set(); }
};
template <typename T>
void test_internal() {
T x;
x.dump();
x.set();
x.dump();
}
template <typename T>
void test() {
test_internal<T>();
test_internal<T>();
}
int main()
{
test<Foo>(); // prints ??, 5, 5, 5, where ?? is a random number, possibly 0
test<Bar>(); // prints ??, 5, 5, 5
test<Bar2>(); // prints 0, 5, 0, 5
}
Теперь, если Foo имел определенный пользователем конструктора, то это будет всегда инициализироваться независимо от того, имеет ли Bar или нет пользовательский инициализированный конструктор. Если Bar имеет пользовательский конструктор, который явно вызывает (возможно неявно определенный) конструктор Foo, то Foo фактически будет инициализирован. Если список инициализации Bar не вызывает конструктор Foo, то он будет эквивалентен случаю, когда Bar не имеет определенного пользователем конструктора.
Для проверки кода может потребоваться разъяснение. Нам интересно, инициализирует ли компилятор переменную без кода пользователя, фактически вызывающего конструктор. Мы хотим проверить, инициализирован ли объект или нет. Теперь, если мы просто создадим объект в функции, это может привести к удалению позиции памяти, которая была не затронута и уже содержит нули. Мы хотим отличить удачу от успеха, поэтому мы определяем переменную в функции и дважды вызываем ее. В первом запуске он распечатает содержимое памяти и принудительно изменит ее. Во втором вызове функции, поскольку трассировка стека одинакова, переменная будет находиться в точно такой же позиции памяти. Если он был инициализирован, он будет установлен в 0, иначе он сохранит то же значение, что и старая переменная в точно такой же позиции.
В каждом из тестовых прогонов первое напечатанное значение - это инициализированное значение (если оно было фактически инициализировано) или значение в этой позиции памяти, что в некоторых случаях бывает равным 0. Второе значение - это просто тест токен, представляющий значение в позиции памяти после его ручной смены. Третье значение происходит от второго запуска функции. Если переменная инициализируется, она вернется к 0. Если объект не инициализирован, его память сохранит старое содержимое.
Я знаком с C++, и у меня все еще есть некоторые сомнения в такой степени каждый так часто. Более того, большинство ответов прямо указывают, что будет вызываться конструктор по умолчанию Foo, и факт в том, что он зависит от определения самого Foo. Является ли он предоставленным пользователем или неявным конструктором по умолчанию? Имеет ли он какие-либо атрибуты частного участника? Инициализация на C++ не проста. –
Очень забавно, что @xtofl просит плакат удалить «Я знаком с C++» ... Может быть, большинство людей не так знакомы с C++, когда почти все ответы ошибочны. На самом деле инициализация тяжелая, некоторые из людей, которые ответили, доказали свои знания на C++ @JaredPar, @dirkgently, @David Thornley и все же не смогли. –