Espacios de nombres
Variantes

Inicialización de agregado

De cppreference.com

Inicializa un agregado a partir de una lista de inicializadores entre llaves. Es una forma de inicialización de lista (desde C++11).

Sintaxis

T object = { arg1, arg2, ... }; (1)
T object { arg1, arg2, ... }; (2) (desde C++11)
T object = { .des1 = arg1 , .des2 { arg2 } ... }; (3) (desde C++20)
T object { .des1 = arg1 , .des2 { arg2 } ... }; (4) (desde C++20)
1,2) Inicialización de un agregado con una lista de inicializadores normal.
3,4) Inicialización de un agregado con inicializadores designados (solo clase agregado).

Definiciones

Agregado

Un agregado es uno de los siguientes tipos:

  • tipos array;
  • tipos clase que no tienen:
  • constructores declarados por el usuario
(hasta C++11)
(desde C++11)
(hasta C++20)
  • constructores declarados por el usuario o heredados
(desde C++20)
  • datos miembros directos no-estáticos privados o protegidos
(hasta C++17)
(desde C++17)
  • funciones miembro virtuales
(desde C++11)
(hasta C++14)

Elemento

Los elementos de un agregado son:

  • para un array, los elementos del array en orden creciente de subíndice, o
  • para una clase, los datos miembro no estáticos que no son campos de bits anónimos, en orden de declaración.
(hasta C++17)
  • para una clase, las clases base directas en orden de declaración, seguidas de los datos miembro no estáticos directos que no son campos de bits anónimos ni miembros de una unión anónima, en orden de declaración.
(desde C++17)

Pertenencia

Se dice que cada cláusula inicializadora en una lista de inicializadores entre llaves pertenece a un elemento del agregado que se está inicializando o a un elemento de uno de sus subagregados.

Teniendo en cuenta la secuencia de cláusulas inicializadoras y la secuencia de elementos agregados inicialmente formada como la secuencia de elementos del agregado que se está inicializando y potencialmente modificada como se describe a continuación:

  • Para cada cláusula inicializadora, si se cumple alguna de las siguientes condiciones, pertenece al elemento agregado correspondiente elem:
  • elem no es un agregado.
  • La cláusula inicializadora comienza con {.
  • La cláusula inicializadora es una expresión y se puede formar una secuencia de conversión implícita que convierta la expresión al tipo de elem.
  • elem es un agregado que en sí mismo no tiene elementos agregados.
  • De lo contrario, elem es un agregado y ese subagregado se reemplaza en la lista de elementos agregados por la secuencia de sus propios elementos agregados, y el análisis de pertenencia se reanuda con el primer elemento de ese tipo y la misma cláusula inicializadora. En otras palabras, estas reglas se aplican recursivamente a los subagregados del agregado.

El análisis se completa cuando se han agotado todas las cláusulas inicializadoras. Si queda alguna cláusula inicializadora que no pertenezca a un elemento del agregado o a uno de sus subagregados, el programa está mal formado.

struct S1 { int a, b; };
struct S2 { S1 s, t; };

// Cada subagregado de “x” pertenece a una cláusula inicializadora que comienza con {S2 x[2] =
{
    // pertenece a “x[0]”
    {
        {1, 2}, // pertenece a “x[0].s”
        {3, 4}  // pertenece a “x[0].t”
    },
    // pertenece a “x[1]”
    {
        {5, 6}, // pertenece a “x[1].s”
        {7, 8}  // pertenece a “x[1].t”
    }
};

// “x” e “y” tienen el mismo valor (ver abajo)
S2 y[2] = {1, 2, 3, 4, 5, 6, 7, 8};

// El proceso del análisis de pertenencia de “y”:
// 1. Inicializa la secuencia de elementos agregados (x[0], x[1]) y
//    la secuencia de cláusulas inicializadoras (1, 2, 3, 4, 5, 6, 7, 8).
// 2. A partir de los primeros elementos de cada secuencia,
//    verifica si 1 pertenece a x[0]:
//    · x[0] es un agregado.
//    · 1 no comienza con {.
//    · 1 es una expresión, pero no se puede convertir implícitamente a S2.
//    · x[0] tiene elementos agregados.
// 3. 0 no puede pertenecer a x[0], por lo tanto x[0] se reemplaza por x[0].s y x[0].t,
//    la secuencia de elementos agregados se convierte en (x[0].s, x[0].t, x[1]).
// 4. Reanuda la comprobación de pertenencia, pero 1 tampoco puede pertenecer a x[0].s.
// 5. La secuencia de elementos agregados ahora se convierte en (x[0].s.a, x[0].s.b, x[0].t, x[1]).
// 6. Reanuda nuevamente la comprobación de pertenencia:
//    1 pertenece a x[0].s.a, y 2 pertenece a x[0].s.b.
// 7. El resto del análisis de pertenencia funciona de manera similar.

char cv[4] = {'a', 's', 'd', 'f', 0}; // ERROR: demasiadas cláusulas de inicialización

Proceso de inicialización

Determinación del tipo de elemento

Los efectos de la inicialización de agregado son:

1) Determina los elementos inicializados explícitamente del agregado de la siguiente manera:
  • Si la lista de inicializadores es una lista de inicializadores designados (el agregado solo puede ser de tipo clase), el identificador en cada designador debe nombrar un dato miembro no estático directo de la clase, y los elementos inicializados explícitamente del agregado son los elementos que son, o contienen, esos miembros.
(desde C++20)
  • De lo contrario, si la lista de inicializadores no está vacía, los elementos inicializados explícitamente del agregado son los elementos con una cláusula de inicializador correspondiente y los elementos que tienen un subagregado con una cláusula de inicializador correspondiente.
  • De lo contrario, la lista de inicializadores debe estar vacía ({}), y no hay elementos inicializados explícitamente.
El programa está mal formado si el agregado es una unión y hay dos o más elementos inicializados explícitamente:

Los efectos de la inicialización de agregado son:

union u { int a; const char* b; };

u a = {1};                   // OK: inicializa explícitamente el miembro `a`
u b = {0, "asdf"};           // ERROR: inicializa explícitamente dos miembros
u c = {"asdf"};              // ERROR: int no puede ser inicializado por "asdf"

// Listas de inicializadores designados de C++20
u d = {.b = "asdf"};         // OK: puede inicializar explícitamente un miembro no inicial
u e = {.a = 1, .b = "asdf"}; // ERROR: inicializa explícitamente dos miembros
2) Inicializa cada elemento del agregado en el orden de los elementos. Es decir, todos los cálculos de valores y efectos secundarios asociados con un elemento dado se secuencian antes de aquellos de cualquier elemento que lo siga en orden (desde C++11).

Elementos inicializados explícitamente

Para cada elemento inicializado explícitamente: