Подтвердить что ты не робот

T v {} инициализация

Я читаю стандарт С++ 11, но не могу понять,

T x{};

инициализируется значением или инициализируется по умолчанию (автоматическое хранилище). Он довольно четко говорит, что:

10 Объект, инициализатор которого представляет собой пустой набор скобок, т.е.(), должен инициализироваться значением.

И что

11 Если для объекта не задан инициализатор, объект инициализируется по умолчанию:

Но все, что я могу найти о T x{};, это то, что:

Инициализация, которая происходит в формах T x (a); T x {a}; а также в новых выражениях (5.3.4), выражения static_cast (5.2.9), преобразования типа функциональных обозначений (5.2.3) и инициализаторы базиса и члена (12.6.2), называются прямой инициализацией.

и

Если инициализатор представляет собой (не заключенный в скобки) бит-init-list, объект или ссылка инициализируется по списку (8.5.4).

Я новичок в погружении в уровень чтения стандартов. Может ли кто-нибудь указать мне в правильном направлении?

4b9b3361

Ответ 1

Это действительно покрывается вашей цитатой:

Если инициализатор представляет собой (не заключенный в скобки) бит-init-list, объект или ссылка инициализируется по списку (8.5.4).

Переход до 8.5.4 Инициализация списка. Здесь я перефразировал/пропустил некоторые моменты, которые не относятся к случаю T x{}:

Список-инициализация объекта или ссылки типа T определяется следующим образом:

  • Если T является агрегатом, выполняется агрегатная инициализация (8.5.1).
  • В противном случае, если в списке инициализаторов нет элементов, а T - тип класса с конструктором по умолчанию, объект инициализируется значением
  • В противном случае, если T является специализацией std::initializer_list<E> [...]
  • В противном случае [если список не пуст и соответствует конструктору]
  • В противном случае, [если список имеет один элемент]
  • В противном случае, если T является ссылочным типом]
  • В противном случае, если в списке инициализаторов нет элементов, объект инициализируется значением.
  • В противном случае программа плохо сформирована.

Первая точка, агрегатная инициализация была также в С++ 03; в этом случае T x{}; совпадает с T x = {};.

Для второй точки "T - тип класса с конструктором по умолчанию", это инициализируется значением, что означает вызов конструктора по умолчанию.

Если T является примитивным типом, то применяется вторая-последняя точка и снова инициализируется инициализацией значения.

Возвращаясь к суммарному случаю инициализации, в 8.5.1/7 есть:

Если в списке меньше предложений-инициализаторов, чем в совокупности, то каждый член, явно не инициализированный, должен быть инициализирован из своего элемента с равным-равным-инициализатором или, если нет скобок или равно -initializer, из пустого списка инициализаторов (8.5.4).

Инициализатор, основанный на скобках или равных, относится к инициализатору, предоставленному встроенным в определение класса. Если этого нет, то он инициализируется так, как если бы элемент был инициализирован с помощью {} (так что эта логика рекурсивно применяется для каждого элемента агрегата).

Например,

struct T
{
     int a;
};

то T x {}; приводит к инициализации a, как если бы он был int a{};, который является инициализацией значения, так как int является примитивным типом.

Ответ 2

Хотя Мэтт Макнабб уже рассказал об этом, я добавлю, что если у вас возникнут проблемы с переходом по стандарту, то не стоит проверять cppreference. Их раздел в инициализации списка очень хорошо меняет его.

По существу, как и ваша стандартная цитата, T x{}; относится к:

инициализация именованной переменной с вложенным в скобки списком выражения или вложенные списки (braced-init-list).

и

Эффекты инициализации списка объекта типа T:

  • Если список braced-init пуст и T - тип класса с конструктором по умолчанию, выполняется инициализация значения.

[...]

  • В противном случае, если в файле braced-init-list нет элементов, T инициализируется значением.