Значения по умолчанию в списках инициализаторов С++
Я только вчера узнал, что указание параметров для элементов списка инициализаций является необязательным. Однако каковы правила того, что происходит в этом случае?
В приведенном ниже примере инициализируется ptr до 0, переключается на false и Bar по умолчанию построено? Я предполагаю, что этот вопрос является своего рода избыточным, потому что в списках инициализаторов мало смысла, если неопределенные значения аргументов == undefined.
Могу ли я также указать на раздел стандарта С++, в котором указано поведение в случае элементов списка инициализаций, не заданных аргументами?
class Bar
{
Bar() { }
};
class SomeClass;
class AnotherClass
{
public:
SomeClass *ptr;
bool toggle;
Bar bar;
AnotherClass() : ptr(), toggle(), bar() { }
// as opposed to...
// AnotherClass() : ptr(NULL), toggle(false), bar(Bar()) { }
};
Ответы
Ответ 1
Да, члены будут инициализированы до нуля и объекта, построенного по умолчанию, соответственно.
Стандарт С++ 11 определяет это поведение в 12.6.2/7:
Используется список выражений-list или braced-init-list в mem-initializer для инициализации указанного подобъекта (или, в случае делегирующий конструктор, полный объект класса) в соответствии с правила инициализации 8.5 для прямой инициализации.
В свою очередь, 8.5/10 гласит:
Объект, инициализатор которого представляет собой пустой набор скобок, т.е.(), должен инициализироваться значением.
Параграф 8.5/7 определяет инициализацию значения:
Для инициализации объекта типа типа T означает:
- если T является (возможно, cv-квалифицированным) типом класса (раздел 9) с предоставленным пользователем конструктором (12.1), то конструктор по умолчанию для T называется (и инициализация плохо сформирована, если T не имеет доступного значения по умолчанию Конструктор);
- если T является (возможно, cv-квалифицированным) классом типа non-union без созданного пользователем конструктора, тогда объект нулевой инициализации и, если Ts неявно объявленный конструктор по умолчанию является нетривиальным, этот конструктор называется.
- если T - тип массива, то каждый элемент инициализируется значением;
- в противном случае объект нулевой инициализируется.
И, наконец, 8.5/5 определяет нуль-инициализацию:
Для нулевой инициализации объекта или ссылки типа T означает:
- если T является скалярного типа (3.9), объект устанавливается в значение 0 (ноль), взятое как интегральное постоянное выражение, преобразованное в T;
- если T является (возможно, cv-квалифицированным) классом типа non-union, каждый нестатический данные член и каждый подобъект базового класса инициализируются нулем и заполняются инициализируется нулевыми битами;
- если T является (возможно, cv-квалифицированным) объединением тип, первый элемент нестатического имени объектов, инициализируется и заполняется инициализируется нулевыми битами;
- если T является тип массива, каждый элемент инициализируется нулем;
- если T является ссылкой тип, инициализация не выполняется.
Ответ 2
В приведенном ниже примере инициализируется ptr до 0, переключается на false, а Bar по умолчанию - построено?
Да. Если инициатор-член появляется в списке инициализации с пустыми круглыми скобками, то этот элемент инициализируется значением. Это означает, что числовые типы будут инициализированы до нуля, указатели на нуль и классы с конструкторами по умолчанию, использующие этот конструктор.
Если вы не включаете участника в список инициализации вообще, тогда он будет инициализироваться по умолчанию; в таком случае. числовые и указательные типы останутся неинициализированными.
Могу ли я также указать на раздел стандарта С++, в котором указано поведение в случае элементов списка инициализаций, не заданных аргументами?
С++ 11 12.6.2/7 указывает, что правила те же, что и для прямой инициализации.
С++ 11 8.5/16 указывает, что если инициализатор ()
, объект инициализируется значением.
С++ 11 8.5/7 определяет инициализацию значения.
Ответ 3
Инициализация рассматривается в [dcl.init] (aka 8.5)
В пункте 10 говорится:
Объект, инициализатор которого представляет собой пустой набор скобок, т.е.(), должен инициализироваться значением.
Инициализация значения - это просто построение по умолчанию для классов и нулевая инициализация для неклассовых типов.