11 Declarators [dcl.decl]

11.6 Initializers [dcl.init]

11.6.1 Aggregates [dcl.init.aggr]

Anaggregate - это массив илиclass с

  • нет предоставленных пользователемexplicitили унаследованных конструкторов ([class.ctor]),

  • нет частных или защищенных нестатических элементов данных (пункт[class.access]),

  • нетvirtual functions, и

  • нет виртуальных, частных или защищенных базовых классов ([class.mi]).

[ Note: Агрегированная инициализация не позволяет получить доступ к защищенным и закрытым членам или конструкторам базового класса. ]end note

Вelements состав агрегата входят:

  • для массива элементы массива в порядке возрастания индекса, или

  • для класса - прямые базовые классы в порядке объявления, за которыми следуют прямые нестатические элементы данных ([class.mem]), которые не являются членами анонимного объединения, в порядке объявления.

Когда агрегат инициализируется списком инициализаторов, как указано в[dcl.init.list], элементы списка инициализаторов принимаются в качестве инициализаторов для элементов агрегата по порядку. Каждый элемент инициализируется копией из соответствующего initializer-clause. Если initializer-clause- это выражение, аnarrowing conversion для преобразования выражения требуется a , программа имеет неправильный формат . [ Note: Если initializer-clauseсам является списком инициализатора, элемент инициализируется списком, что приведет к рекурсивному применению правил в этом разделе, если элемент является агрегатом. ] [end noteExample:

struct A {
  int x;
  struct B {
    int i;
    int j;
  } b;
} a = { 1, { 2, 3 } };

инициализируется a.x 1, a.b.i 2, a.b.j 3.

struct base1 { int b1, b2 = 42; };
struct base2 {
  base2() {
    b3 = 42;
  }
  int b3;
};
struct derived : base1, base2 {
  int d;
};

derived d1{{1, 2}, {}, 4};
derived d2{{}, {}, 4};

инициализируется d1.b1 с 1, d1.b2 с 2, d1.b3 с 42, d1.d с 4 и d2.b1 с 0, d2.b2 с 42, d2.b3 с 42, d2.d с 4. ]end example

Агрегат, являющийся классом, также может быть инициализирован одним выражением, не заключенным в фигурные скобки, как описано в[dcl.init].

Массив с неизвестной границей, инициализированный заключенным в фигурные скобки initializer-list содержащим , где должно быть больше нуля, определяется как имеющий elements ( ). [n initializer-clausesnn[dcl.array]Example:

int x[] = { 1, 3, 5 };

объявляется и инициализируется x как одномерный массив, состоящий из трех элементов, поскольку размер не был указан и имеется три инициализатора. ] Пустой список инициализаторов не должен использоваться в качестве массива с неизвестной границей. [ Инициализатор члена по умолчанию не определяет границу для массива элементов с неизвестной границей. Поскольку инициализатор члена по умолчанию игнорируется, если присутствует подходящий ( ), инициализатор члена по умолчанию не считается инициализирующим массив с неизвестной границей. [end example{}initializer-clause105Note: mem-initializer[class.base.init]Example:

struct S {
  int y[] = { 0 };          // error: non-static data member of incomplete type
};

end example] ]end note

[ Note: Статические элементы данных и безымянные битовые поля не считаются элементами агрегата. [Example:

struct A {
  int i;
  static int s;
  int j;
  int :17;
  int k;
} a = { 1, 2, 3 };

Здесь инициализируется второй инициализатор 2, a.j а не статический элемент данных A​::​s, и инициализируется третий инициализатор 3,a.k а не безымянное битовое поле перед ним. ] ]end exampleend note

initializer-list Плохо сформированный , если число initializer-clauses превышает количество элементов , чтобы инициализировать. [Example:

char cv[4] = { 'a', 's', 'd', 'f', 0 };     // error

плохо сформирован. ]end example

Если initializer-clauses в списке меньше элементов, чем элементов в агрегате без объединения, то каждый элемент, не инициализированный явно, инициализируется следующим образом:

  • Если элемент имеет инициализатор члена по умолчанию ([class.mem]), элемент инициализируется этим инициализатором.

  • В противном случае, если элемент не является ссылкой, элемент инициализируется копией из пустого списка инициализаторов ([dcl.init.list]).

  • В противном случае программа имеет неверный формат.

Если агрегат является объединением, а список инициализаторов пуст, тогда

  • если какой-либо вариантный член имеет инициализатор члена по умолчанию, этот член инициализируется из его инициализатора члена по умолчанию;

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

[Example:

struct S { int a; const char* b; int c; int d = b[a]; };
S ss = { 1, "asdf" };

инициализируется ss.a с 1, ss.b с"asdf", ss.c значением выражения формы int{} (то есть,0), иss.d значениемss.b[ss.a] (то есть,'s'), и в

struct X { int i, j, k = 42; };
X a[] = { 1, 2, 3, 4, 5, 6 };
X b[2] = { { 1, 2, 3 }, { 4, 5, 6 } };

a иb иметь такое же значение ]end example

Если ссылочный член инициализируется из его инициализатора члена по умолчанию, а его потенциально оцененное подвыражение является агрегированной инициализацией, которая будет использовать этот инициализатор члена по умолчанию, программа сформирована неправильно. [Example:

  struct A;
  extern A a;
  struct A {
    const A& a1 { A{a,a} };     // OK
    const A& a2 { A{} };        // error
  };
  A a{a,a};                     // OK

end example]

Если совокупный классC содержит субагрегатный элемент e без элементов, initializer-clausefore не должен быть опущен в initializer-listдля объекта типа, C если также не пропущены initializer-clauses для всехC следующих элементовe . [Example:

struct S { } s;
struct A {
  S s1;
  int i1;
  S s2;
  int i2;
  S s3;
  int i3;
} a = {
  { },              // Required initialization
  0,
  s,                // Required initialization
  0
};                  // Initialization not required for A​::​s3 because A​::​i3 is also not initialized

end example]

При инициализации многомерного массива initializer-clauses элементы инициализируются с последним (крайним правым) индексом массива, изменяющим самый быстрый ([dcl.array]). [Example:

int x[2][2] = { 3, 1, 4, 2 };

инициализируется x[0][0] в 3, x[0][1] в 1, x[1][0] в 4и x[1][1] в 2. С другой стороны,

float y[4][3] = {
  { 1 }, { 2 }, { 3 }, { 4 }
};

инициализирует первый столбец y (рассматриваемого как двумерный массив), а остальные оставляет равными нулю. ]end example

Скобки можно опустить initializer-list следующим образом. Если initializer-list начинается с левой фигурной скобки, то следующий разделенный запятыми список initializer-clauses инициализирует элементы подагрегата; ошибочно, что существует нечто большее, initializer-clauses чем элементы. Если, однако, initializer-list для субагрегата не начинается с левой фигурной скобки, тогда initializer-clauses из списка берется только достаточно для инициализации элементов субагрегата; любые оставшиеся initializer-clauses остаются для инициализации следующего элемента агрегата, элементом которого является текущий подагрегат. [Example:

float y[4][3] = {
  { 1, 3, 5 },
  { 2, 4, 6 },
  { 3, 5, 7 },
};

является полностью-приготовился инициализации: 1, 3, 5 и инициализировать первую строку массива y[0], а именно y[0][0], y[0][1], и y[0][2]. Аналогичным образом следующие две строки инициализируют y[1] и y[2]. Инициализатор завершается раньше, и поэтому y[3]элементы s инициализируются, как если бы они были явно инициализированы выражением формы float(), то есть инициализируются с помощью 0.0. В следующем примере фигурные скобки initializer-list опущены; однако initializer-list имеет тот же эффект, что и полностью закрепленный initializer-list в приведенном выше примере,

float y[4][3] = {
  1, 3, 5, 2, 4, 6, 3, 5, 7
};

Инициализатор fory начинается с левой фигурной скобки, а инициализатор for - y[0] нет, поэтому используются три элемента из списка. Аналогичным образом следующие три берутся последовательно за y[1] и y[2]. ]end example

Все неявные преобразования типов (Clause[conv]) учитываются при инициализации элемента с помощью assignment-expression. Если assignment-expression может инициализировать элемент, он инициализируется. В противном случае, если элемент сам является субагрегатом, предполагается исключение фигурных скобок и assignment-expression рассматривается для инициализации первого элемента субагрегата. [ Note: Как указано выше, исключение скобок не может применяться к субагрегатам без элементов; требуется initializer-clauseдля всего подобъекта. ]end note

[Example:

struct A {
  int i;
  operator int();
};
struct B {
  A a1, a2;
  int z;
};
A a;
B b = { 4, a, a };

Брекеты опускаются во всем initializer-clause для b.a1.i. b.a1.i инициализируется с помощью 4, b.a2 инициализируется с помощью a, b.z инициализируется любым a.operator int() возвратом. ]end example

[ Note: Агрегатный массив или агрегатный класс могут содержать элементы типа класса с предоставленным пользователем конструктором ([class.ctor]). Инициализация этих агрегированных объектов описана в[class.expl.init]. ]end note

[ Note: Ли инициализация агрегатов со статической продолжительностью хранения статический или динамический задается в[basic.start.static],[basic.start.dynamic]и[stmt.dcl]. ]end note

Когда объединение инициализируется с помощью инициализатора, заключенного в фигурные скобки, фигурные скобки должны содержать только initializer-clause первый нестатический член данных объединения. [Example:

union u { int a; const char* b; };
u a = { 1 };
u b = a;
u c = 1;                        // error
u d = { 0, "asdf" };            // error
u e = { "asdf" };               // error

end example]

[ Note: Как описано выше, фигурные скобки вокруг initializer-clause члена объединения можно опустить, если объединение является членом другого агрегата. ]end note

Синтаксис предусматривает пустые initializer-lists, но, тем не менее, C ++ не имеет массивов нулевой длины.