c++ - son - ventajas y desventajas de las listas abiertas
¿Qué es una lista cerrada de corsé si no es una lista inicial? (4)
Hice una pregunta aquí: Lifetime Extension de una declaración initializer_list que implica el código no funcional:
const auto foo = [](const auto& a, const auto& b, const auto& c) { return {a, b, c}; };
intializer_list
que la lambda intentaba devolver una lista intializer_list
(eso es malo, no hagas eso). Pero tengo un comment :
No es una
initializer_list
, es una lista de inicializadores. Dos cosas diferentes
Solo pensé que cada vez que hacía una lista de intializer_list
estaba creando una intializer_list
. Si eso no es lo que está pasando, ¿qué es una lista de llaves?
Solo pensé que cada vez que hacía una lista de
intializer_list
estaba creando unaintializer_list
.
Eso no es correcto
Si eso no es lo que está pasando, ¿qué es una lista de llaves?
struct Foo {int a; int b;};
Foo f = {10, 20};
La parte {10, 20}
no es una initializer_list
. Es solo una forma sintáctica para usar una lista de objetos para crear otro objeto.
int a[] = {10, 20, 30};
Una vez más, es una forma sintáctica para crear una matriz.
El nombre para la forma sintáctica es braced-init-list
.
Aquí hay tres conceptos distintos, pero relacionados:
braced-init-list : la regla gramatical asociada con las listas de llaves incluidas en ciertos contextos.
Lista de inicializador: el nombre para el inicializador de lista de inicialización de braced utilizado en la inicialización de lista .
std::initializer_list
: una clase que envuelve una matriz temporal que se crea en algunos contextos que incluyen braced-init-list s.
Algunos ejemplos:
//a braced-init-list and initializer list,
//but doesn''t create a std::initializer_list
int a {4};
//a braced-init-list and initializer list,
//creates a std::initializer_list
std::vector b {1, 2, 3};
//a braced-init-list and initializer list,
//does not create a std::initializer_list (aggregate initialization)
int c[] = {1, 2, 3};
//d is a std::initializer_list created from an initializer list
std::initializer_list d {1, 2, 3};
//e is std::initializer_list<int>
auto e = { 4 };
//f used to be a std::initializer_list<int>, but is now int after N3922
auto f { 4 };
Es posible que desee leer N3922 , que cambió algunas de las reglas que implican auto
y std::initializer_list
.
Es una lista inicial arrinconada . Una lista de std::initializer_list
existía antes de std::initializer_list
y se usa para inicializar agregados .
int arr[] = {1,2,3,4,5};
Lo anterior usó una lista de inicio reforzada para inicializar la matriz, no se creó std::initializer_list
. Por otro lado, cuando lo haces
std::vector<int> foo = {1,2,3,4,5};
foo
no es un agregado, por lo que la lista de inicio de llaves forzadas se usa para crear una lista std::initializer_list
que luego se pasa al constructor de foo
que acepta una lista std::initializer_list
.
Una cosa a tener en cuenta acerca de una lista de inicio reforzada es que no tiene ningún tipo, por lo que se desarrollaron reglas especiales para usar con ella y auto
. Tiene el siguiente comportamiento (desde la adopción de N3922 )
auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int>
auto x2 = { 1, 2.0 }; // error: cannot deduce element type
auto x3{ 1, 2 }; // error: not a single element
auto x4 = { 3 }; // decltype(x4) is std::initializer_list<int>
auto x5{ 3 }; // decltype(x5) is int
Y puede obtener más información sobre el historial de este comportamiento y por qué se modificó en: ¿Por qué auto x {3} deduce una initializer_list?
Tienes dos cosas diferentes cuando usas {}
- A Tipo
std::initializer_list<T>
donde los valores se pueden convertir implícitamente aT
- Un tipo que se puede inicializar con los valores de la lista.
El primer tipo fuerza una lista homogénea y el segundo tipo no. En el siguiente ejemplo:
struct S{
int a;
string b
};
void f1( S s );
void f2( int i );
void f3( std::initializer_list<int> l );
f1( {1, "zhen"} ); // construct a temporal S
f2( {1} ); // construct a temporal int
f3( {1,2,3} ); // construct a temporal list of ints
Las funciones f1 y f2 usan el primer tipo y f3 usan el segundo tipo. Debe saber que si hay ambigüedad, se prefiere std :: initializer_list. P.ej:
void f( S s );
void f( int i );
void f( std::initializer_list<int> l );
f( {1, "zhen"} ); // calls with struct S
f( {1} ); // calls with int list with one element
f( {1,2,3} ); // calls with int list with three elements