2009-12-08 13 views
12

¿Hay una regla de oro para decidir cuándo utilizar la sintaxis de edad () en lugar de la nueva sintaxis {}?Inicialización uniforme en C++ 0x, cuándo usar() en lugar de {}?

Para inicializar una estructura:

struct myclass 
{ 
    myclass(int px, int py) : x(px), y(py) {} 
private: 
    int x, y; 
}; 
... 
myclass object{0, 0}; 

Ahora bien, en el caso de un vector por ejemplo, que tiene muchos constructores. Siempre hago lo siguiente:

vector<double> numbers{10}; 

consigo un vector de elemento en lugar de uno con elementos como uno de los constructores es:

explicit vector (size_type n, const T& value= T(), const Allocator& = Allocator()); 

Mi sospecha es que cada vez que una class define un constructor initializer list como en el caso de un vector, se llama con la sintaxis {}.

Entonces, es lo que estoy pensando es correcto. es decir, ¿Debería volver a la sintaxis anterior solo cuando una clase defina un constructor de listas de inicializadores para llamar a un constructor diferente? p. Ej. para corregir el código anterior:

vector<double> numbers(10); // 10 elements instead of just one element with value=10 
+6

¿Eso significa que se pueden romper los clientes de una clase al agregar constructores de lista de inicializadores? Ay. –

+2

No, el constructor del inicializador no afecta a los otros constructores en su lugar AFAIK. –

+1

@dribeas: ¿Eso es cierto? Supongamos que su clase tiene inicialmente un constructor que toma un solo argumento int y crea felizmente instancias con la nueva sintaxis. Si se agrega un nuevo constructor que toma 'initializer_list ', ¿no estarían todos esos objetos usando el constructor agregado? A menos que los ejemplos en la red estén desactualizados y declarar que un vector con la lista debería verse como 'vector v {{2, 1}};' No veo corchetes que vayan a ninguna parte. – UncleBens

Respuesta

2

Tome un vistazo a esto:

http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=453&rll=1

el uso de un {} inicializadores al estilo de una variable no tiene ninguna asignación directa a las listas de inicialización en ningún constructor de la clase. Esas listas de inicialización de constructores se pueden agregar/eliminar/modificar sin interrumpir las llamadas existentes.

Básicamente, el comportamiento diferente del contenedor es especial y requiere un código especial en ese contenedor, específicamente un constructor que toma un std::initializer_list. Para POD y objetos simples, puede usar {} y () de manera intercambiable.

+0

"Para POD y objetos simples, puede usar {} y() indistintamente." No, '()' solo funciona si hay un constructor, que (aparte del constructor de copia) descalifica al objeto de ser POD. '{}' por otro lado todavía funciona. – Potatoswatter

9

He encontrado la respuesta en los documentos estándar (latest draft). Con suerte, trataré de explicar lo que entendí.

primer lugar, si una clase define un constructor lista de inicialización, entonces se utiliza siempre adecuado:

§ 8.5.4 (página 203)

inicializador de lista de constructores se favorecidas sobre otros constructores en lista-inicialización (13.3.1.7).

Creo que esta es una gran característica a tener, lo que elimina el dolor de cabeza asociado con el estilo no uniforme :)

De todos modos, la única Gotcha (que mi pregunta es sobre) es que si diseña una clase sin el constructor del inicializador, luego la agregas más tarde, puedes obtener un resultado sorprendente.

Básicamente, imagine std::vector no tenía la lista de inicialización del constructor, entonces lo siguiente sería crear un vector con 10 elementos:

std::vector<int> numbers{10}; 

Al añadir la lista de inicialización del constructor, el compilador favorecería que sobre el otro constructor debido a la sintaxis {}. Este comportamiento ocurriría porque los elementos de la lista de inicio {10}son aceptados mediante el constructor init-list. Si no hay una conversión aceptable, se utilizará cualquier otro constructor, por ejemplo:

std::vector<string> vec{10}; 
// a vector of 10 elements. 
// the usual constructor got used because "{0}" 
// is not accepted as an init-list of type string. 
Cuestiones relacionadas