tipos programa lenguaje funciones ejemplos datos comandos codigos basicos c++ c++11 uniform-initialization

programa - ¿Cómo usar la sintaxis de inicialización uniforme de C++ 11?



programa c++ (3)

No puedo entender cuándo y cómo usar la nueva sintaxis de inicialización uniforme en C ++ 11.
Por ejemplo, entiendo esto:

std::string a{"hello world"}; // OK std::string b{a}; // NOT OK

¿Por qué no funciona en el segundo caso? El error es:

error: no matching function for call to ‘std::basic_string<char>::basic_string(<brace enclosed initializer list>)’

con esta versión de g ++ g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2 .

Y con datos primitivos, ¿qué sintaxis debería usar?

int i = 5; int i{5}; int i = {5};


El error de compilación para

// T t{u}; std::string a; std::string b{a};

Es una combinación de cuatro cosas

  • El borrador hasta hace poco tiempo dijo que si T tiene un constructor de lista inicializadora ( std::string tiene uno, tomando elementos char ), la lista de inicializadores se pasa a sí misma como un argumento. Entonces, el argumento para el constructor (es) no es a , sino {a} .

  • El borrador dice que una lista de inicializadores que inicializa una referencia no se realiza mediante enlace directo, sino que primero se construye una salida temporal del elemento en la lista de inicializadores y luego se vincula la referencia de destino a esa referencia temporal.

  • El borrador dice que al inicializar una referencia mediante una lista de inicializadores, cuando la inicialización de la referencia no es vinculante directa, la secuencia de conversión es una secuencia de conversión definida por el usuario.

  • El borrador dice que al pasar la lista de inicializadores al considerar constructores de clase X como candidatos en un escenario de resolución de sobrecarga en un contexto como el anterior, cuando se considera un primer parámetro constructor de tipo "referencia a cv X" (cv = const / volátil) - en otras palabras, es muy probable que sea un constructor de copia o movimiento, entonces no se permiten conversiones definidas por el usuario. De lo contrario, si se permite dicha conversión, siempre puede ejecutar en ambigüedades, porque con la inicialización de la lista no está limitado a una conversión anidada definida por el usuario.

La combinación de todo lo anterior es que no se puede usar ningún constructor para tomar {a} . El que usa initializer_list<char> no coincide, y los otros que usan string&& y const string& están prohibidos, porque necesitarían conversiones definidas por el usuario para vincular su parámetro al {a} .

Tenga en cuenta que el borrador más reciente cambió la primera regla: dicen que si ningún constructor de listas de inicializadores puede tomar la lista de inicializadores, entonces la lista de argumentos consta de todos los elementos de la lista de inicializadores. Con esa regla actualizada, su código de ejemplo funcionaría bien.


No funciona porque olvidó el punto y coma:

std::string b{a}; ^^^

De lo contrario, esta sintaxis está bien y llama al constructor de copia.

Para la segunda pregunta, use int i{5}; si quieres ser uniforme, aunque int i = 5; es probablemente más legible


Se supone que el primer ejemplo funciona, llamando al constructor de copia. Si está utilizando GCC, esto se ha solucionado en 4.6.

Los últimos ejemplos tienen una ligera diferencia no estilística.

int i = 5.0; // fine, stores 5 int i{5.0}; // won''t compile! int i = {5.0}; // won''t compile!

La diferencia es que la sintaxis de inicialización uniforme no permite reducir las conversiones. Es posible que desee tener esto en cuenta al elegir entre ellos.