Inicialización de agregado
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) | |||||||
Definiciones
Agregado
Un agregado es uno de los siguientes tipos:
- tipos array;
- tipos clase que no tienen:
|
(hasta C++11) |
|
(desde C++11) (hasta C++20) |
|
(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
|
(hasta C++17) |
|
(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:
elemno 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. elemes un agregado que en sí mismo no tiene elementos agregados.
- De lo contrario,
elemes 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:
|
(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
Elementos inicializados explícitamente
Para cada elemento inicializado explícitamente:
|
|