Пространства имён
Варианты
Действия

Агрегатная инициализация

Материал из cppreference.com
 
 
 
 

Инициализирует агрегат из списка инициализаторов. Это форма инициализации списком. (начиная с C++11)

Синтаксис

T объект = { арг1, арг2, ... }; (1)
T объект { арг1, арг2, ... }; (2) (начиная с C++11)
T объект = { .назн1 = арг1 , .назн2 { арг2 } ... }; (3) (начиная с C++20)
T объект { .назн1 = арг1 , .назн2 { арг2 } ... }; (4) (начиная с C++20)
1,2) Инициализация агрегата обычным списком инициализаторов.
3,4) Инициализация агрегата назначенными инициализаторами (только классовый агрегата).

Объяснение

Определения

Агрегат относится к одному из следующих типов:

  • тип массива
  • классовый тип (обычно struct или union), который имеет
  • нет объявленных пользователем конструкторов
(до C++11)
(начиная с C++11)
(до C++20)
  • нет объявленных пользователем или унаследованных конструкторов
(начиная с C++20)
  • нет закрытых или защищённых прямых (начиная с C++17) нестатических элементов данных
(до C++17)
(начиная с C++17)
  • нет виртуальных функций-элементов
(начиная с C++11)
(до C++14)

Элементами агрегата являются:

  • для массива это элементы массива в порядке возрастания индекса или
  • для класса это нестатические элементы данных, которые не являются анонимными битовыми полями, в порядке объявления.
(до C++17)
  • для класса это прямые базовые классы в порядке объявления, за которыми следуют прямые нестатические элементы данных, которые не являются ни анонимными битовыми полями ни элементами анонимного объединения, в порядке объявления.
(начиная с C++17)

Процесс

Эффекты агрегатной инициализации:

1) Отклоняются следующие ошибочные случаи:
  • количество предложений инициализатора в списке инициализаторов превышает количество элементов агрегата, или
  • инициализируется массив неизвестной привязки с пустым списком инициализаторов ({}).
char cv[4] = {'a', 's', 'd', 'f', 0}; // ошибка
int x[] = {}                          // ошибка
2) Явно инициализированные элементы агрегата определяются следующим образом:
  • Если список инициализаторов является списком назначенных инициализаторов (агрегат может быть только типа класса), идентификатор в каждом указателе должен именовать прямой нестатический элемент данных класса, а явно инициализированные элементы агрегата это элементы, которые являются элементами или содержат эти элементы.
(начиная с C++20)
  • Иначе, если список инициализаторов не пуст, явно инициализированные элементы агрегата являются первыми n элементами агрегата, где n количество элементов в списке инициализаторов.
  • Иначе список инициализаторов должен быть пустым ({}) и не иметь явно инициализированных элементов.
Программа некорректа, если агрегат является объединением и имеется два или более явно инициализированных элемента:
union u { int a; const char* b; };

u a = {1};                   // OK: явно инициализируется элемент `a`
u b = {0, "asdf"};           // ошибка: явно инициализируется два элемента
u c = {"asdf"};              // ошибка: int не может быть инициализирован "asdf"

// списки назначенных инициализаторов C++20
u d = {.b = "asdf"};         // OK: может явно инициализировать неначальный элемент
u e = {.a = 1, .b = "asdf"}; // ошибка: явно инициализируется два элемента
3) Инициализируется каждый элемент агрегата в порядке элементов. То есть все вычисления значений и побочные эффекты, связанные с данным элементом, выполняются до вычислений любого элемента, следующего за ним по порядку (начиная с C++11).

Инициализация элементов

Для каждого явно инициализированного элемента:

  • Если элемент является анонимным элементом объединения, а список инициализаторов является списком назначенных инициализаторов, элемент инициализируется списком назначенных инициализаторов {D}, где D это предложение назначенного инициализатора, именующее элемент элемента анонимного объединения. Должно быть только одно такое предложение назначенного инициализатора.
struct C
{
    union
    {
        int a;
        const