Diferencia de inicialización con o sin llaves en C++11


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 manera diferente o la forma en que se ejecutan estos códigos?

Author: Mikhail, 2014-01-16

2 answers

Versión corta

La inicialización a través de {..} es la inicialización de listas, que prohíbe reducir las conversiones. Por ejemplo, si LLONG_MAX es el valor máximo de un long long int, y su int no puede representar eso:

int x = LLONG_MAX;  // probably accepted with a warning
int x {LLONG_MAX};  // error

Del mismo modo:

long long y = /*something*/;

int x = y;  // accepted, maybe with a warning
int x {y};  // error

Versión larga

Una inicialización de la forma

T x = a;

Es copia-inicialización ; una inicialización de cualquiera de las formas

T x(a);
T x{a};

Es inicialización directa, [dcl.init] / 15-16.

[dcl.init] / 14 entonces dice:

La forma de inicialización (usando paréntesis o =) es generalmente insignificante, pero sí importa cuando el inicializador o la entidad que se inicializa tiene un tipo de clase; vea más 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 del mismo modo, entre estos dos inicializaciones de copia:

T x = a;    // 1
T x = {a};  // 2

Es decir, los que tienen {..} usan inicialización de lista. La {..} se llama lista de inicio entre corchetes.

Por lo tanto, cuando se compara T x = a; con T x {a};, hay dos diferencias: copy - vs.direct-initialization, y "non-list-" vs. list-initialization. Como ya han mencionado otros y en la cita anterior, para tipos que no son de clase T, no hay diferencia entre copy - y direct-init. Sin embargo, hay una diferencia entre list-init y nada de list-init. Es decir, también podríamos comparar

int x (a);
int x {a};

La inicialización de listas en este caso prohíbe reducir las conversiones. Las conversiones de estrechamiento se definen en [dcl.init.list] / 7 as:

Una conversión de estrechamiento es una conversión implícita

  • De un tipo de coma flotante a un tipo entero, o

  • From long double to double or float, or from double to float, except where the source is a constant expression and the actual el valor después de la conversión está dentro del rango de valores que se pueden representar (incluso si no se puede representar exactamente), o

  • De un tipo entero o tipo de enumeración sin ámbito a un tipo de coma flotante, excepto cuando la fuente es una expresión constante y el valor real después de la conversión encajará en el tipo de destino y producir el valor original cuando se convierte de nuevo al tipo original, o

  • Desde un tipo entero o sin codificar tipo de enumeración a un tipo entero que no puede representar todos los valores del tipo original, excepto donde la fuente es una expresión constante cuyo valor después de integral las promociones encajarán en el tipo de destino.

 34
Author: dyp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-16 17:50:28

La primera es la inicialización de la copia, mientras que la segunda es la inicialización de la lista.

Pero, por lo general, la inicialización de copia se usa menos. Porque, si lo está haciendo pasando objetos de tipos definidos por el usuario, solo causa bitcopy y, por lo tanto, puede no producir resultados deseados si la clase definida por el usuario utiliza punteros.

 1
Author: yuvi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-16 06:34:20