c++11 - todas - Diferencia de inicialización con o sin llaves en C++ 11
programacion c++ (3)
Podemos inicializar la variable de dos maneras en C ++ 11
Uno:
int abc = 7;
Dos:
int abc {7};
¿Cuál es la diferencia entre estos dos métodos?
¿Cómo los trata el compilador de forma diferente o cómo se ejecutan estos códigos?
Version corta
La inicialización a través de {..}
es una inicialización de lista, lo que prohíbe la reducción de conversiones. Por ejemplo, si LLONG_MAX
es el valor máximo de un long long int
y long long int
, y su int
no puede representar eso:
int x = LLONG_MAX; // probably accepted with a warning
int x {LLONG_MAX}; // error
Similar:
long long y = /*something*/;
int x = y; // accepted, maybe with a warning
int x {y}; // error
Versión larga
Una inicialización del formulario.
T x = a;
es copia inicialización ; una inicialización de cualquiera de las formas
T x(a);
T x{a};
es la inicialización directa , [dcl.init] / 15-16.
[dcl.init] / 14 luego dice:
La forma de inicialización (usando paréntesis o
=
) es generalmente insignificante, pero importa cuando el inicializador o la entidad que se está inicializando tiene un tipo de clase; vea abajo.
Así que para los tipos que no son de clase, la forma de la inicialización no importa. Sin embargo, hay una diferencia entre estas dos inicializaciones directas:
T x(a); // 1
T x{a}; // 2
y de manera similar, entre estas dos inicializaciones de copia:
T x = a; // 1
T x = {a}; // 2
Es decir, los que tienen {..}
utilizan la inicialización de lista. El {..}
se llama una lista iniciada con corchetes .
Entonces, cuando comparas T x = a;
a T x {a};
, hay dos diferencias: copia-vs inicialización directa, y "non-list-" frente a inicialización de lista. Como ya se mencionó por otros y en la cita anterior, para los tipos T
no son de clase, no hay diferencia entre copy-in y direct-init. Sin embargo, hay una diferencia entre list-init y no list-init. Es decir, podríamos también comparar
int x (a);
int x {a};
La inicialización de listas en este caso prohíbe las conversiones reducidas. Las conversiones de reducción se definen en [dcl.init.list] / 7 como:
Una conversión estrecha es una conversión implícita
de un tipo de punto flotante a un tipo entero, o
de
long double
adouble
ofloat
, o dedouble
afloat
, excepto cuando la fuente es una expresión constante y el valor real después de la conversión está dentro del rango de valores que se pueden representar (incluso si no se puede representar exactamente), odesde un tipo entero o un tipo de enumeración sin ámbito hasta un tipo de punto flotante, excepto cuando el origen es una expresión constante y el valor real después de la conversión se ajustará al tipo objetivo y producirá el valor original cuando se vuelva a convertir al tipo original, o
desde un tipo de entero o un tipo de enumeración sin ámbito hasta un tipo de entero que no puede representar todos los valores del tipo original, excepto cuando la fuente es una expresión constante cuyo valor después de las promociones integrales se ajustará al tipo de destino.
La primera es la inicialización de la copia, mientras que la segunda es la inicialización de la lista.
Pero, usualmente se usa menos la inicialización de copia. Porque, si lo está haciendo al pasar objetos de tipos definidos por el usuario, solo causa copia de bits y, por lo tanto, puede que no produzca resultados esperados si la clase definida por el usuario utiliza punteros.
Mientras que para int
las respuestas existentes están completas, descubrí dolorosamente que, en algunos casos, existen otras diferencias entre las inicializaciones ()
y {}
.
La palabra clave es que {}
es una lista de inicializador.
Uno de estos casos es, la inicialización std::string
con count
copias de un char
:
std::string stars(5, ''*'')
Inicializará stars
como *****
, pero
std::string stars{5, ''*''}
se leerá como std::string stars(char(5), ''*'')
e inicializará star como *
(precedido por un carácter oculto).