Ответ 1
Ожидалось поведение. Существует два понятия: "инициализация по умолчанию" и "инициализация значений". Если вы не указали какой-либо инициализатор, объект "инициализируется по умолчанию", а если вы его упоминаете, даже как() для конструктора по умолчанию, объект "инициализируется значением". Когда конструктор определен, оба случая вызывают конструктор по умолчанию. Но для встроенных типов "инициализация значений" обнуляет память, тогда как "инициализация по умолчанию" не делает.
Итак, когда вы инициализируете:
Type x;
он будет вызывать конструктор по умолчанию, если он указан, но примитивные типы будут неинициализированы. Однако, когда вы указываете инициализатор, например
Type x = {}; // only works for struct/class without constructor
Type x = Type();
Type x{}; // C++11 only
примитивный тип (или примитивные элементы структуры) будет инициализирован VALUE.
Аналогично для:
struct X { int x; X(); };
если вы определяете конструктор
X::X() {}
член x будет неинициализирован, но если вы определите конструктор
X::X() : x() {}
он будет инициализирован VALUE. Это относится и к new
, поэтому
new int;
должен предоставить вам неинициализированную память, но
new int();
должен дать вам память, инициализированную нулем. К сожалению, синтаксис:
Type x();
не допускается из-за неоднозначности грамматики и
Type x = Type();
обязан вызывать конструктор по умолчанию , за которым следует конструктор-копир, если они оба указаны и не являются встроенными.
С++ 11 вводит новый синтаксис,
Type x{};
который можно использовать для обоих случаев. Если вы все еще придерживаетесь более старого стандарта, то почему существует Boost.ValueInitialized, поэтому вы можете правильно инициализировать экземпляр аргумента шаблона.
Более подробное обсуждение может быть найдено, например. в Boost.ValueИнализированная документация.