2012-07-09 23 views
60

Código:¿Por qué es diferente el comportamiento C++ initializer_list para std :: vector y std :: array?

std::vector<int> x{1,2,3,4}; 
std::array<int, 4> y{{1,2,3,4}}; 

¿Por qué necesito llaves dobles rizadas para std :: matriz?

+1

¿Realmente necesita el segundo conjunto de llaves para 'std :: array', o simplemente está recibiendo una advertencia? 'std :: array y {1,2,3,4};' funciona para mí. – bames53

+3

@ bames53: GCC está equivocado al compilar eso. – Xeo

+10

@ Xeo: no es "incorrecto" compilar un programa mal formado con una advertencia. –

Respuesta

55

std::array<T, N> es un agregado: no tiene constructores declarados por el usuario, ni siquiera uno toma un std::initializer_list. Inicialización el uso de llaves se realiza usando inicialización de agregados, una característica de C++ que fue heredado de C.

El "estilo antiguo" de inicialización de agregados utiliza el =:

std::array<int, 4> y = { { 1, 2, 3, 4 } }; 

Con este viejo estilo de agregado inicialización, los apoyos adicionales puede ser elidido, así que esto es equivalente a:

std::array<int, 4> y = { 1, 2, 3, 4 }; 

Sin embargo, estos aparatos adicionales sólo pueden ser elided "en una declaración de la forma T x = { a }; "(C++ 11 §8.5.1/11), es decir, cuando se usa el estilo antiguo =. Esta regla que permite la elisión del corsé no se aplica a la inicialización directa de la lista. Una nota a pie de página aquí dice: "Las llaves no se pueden elidir en otros usos de inicialización de listas".

Hay un informe de defectos con respecto a esta restricción: CWG defect #1270. Si se adopta la propuesta de acuerdo, se le permitirá elisión aparato ortopédico para otras formas de lista de inicialización, y será bien formado lo siguiente: (. Sombrero de punta a Ville Voutilainen para encontrar el informe de defectos)

std::array<int, 4> y{ 1, 2, 3, 4 }; 

+2

No sabía esto; bonito. – chris

+10

Tanto para la inicialización "uniforme" ... – Mehrdad

+3

¿Entonces es una falla del modelo de abstracción que se presenta para 'array'? –

23

Debido std::vector ofrece un constructor que toma en un std::initializer_list<T>, mientras std::array no tiene constructores y el init-lista arriostradas {1, 2, 3, 4} es, de hecho, no se interpreta como una std::initializer_list, pero inicialización de agregados para el interior array de estilo C de std::array (que es donde la El segundo juego de llaves viene de: uno para std::array, uno para e matriz interna de miembros estilo C).

+0

Guau, lo tengo, gracias :) – Sungmin

Cuestiones relacionadas