2011-09-14 6 views
6

estoy tratando el siguiente código:¿El método vector.resize() llama a los constructores de elementos predeterminados al redimensionar?

struct _Struct2 
{ 
    void *ptr; 
    double dval; 
}; 

struct _Struct 
{ 
    float fval; 
    int ival; 
    std::vector<_Struct2> data; 
}; 

std::vector<_Struct> vec; 


int main() 
{ 
    vec.resize(9); 
    for (int i = 0; i < vec.size(); i++) 
    { 
     _Struct &elem = vec[i]; 
     int  len = elem.data.size(); // elem.data is [0]() 
    } 
} 

El cambio de tamaño (9) debería asignar 9 elementos de tipo _Struct. Y, de hecho, funciona. Pero cada elemento del tipo _Struct no se inicializa, especialmente el elemento de datos, que es otro std :: vector. Me gustaría que se inicialice en el std :: vector vacío. ¿Tienes que hacer eso manualmente? Pensé que el método resize() habría llamado el constructor predeterminado de cada elemento _Struct. Thx

Ps. Los nombres de las estructuras utilizadas aquí son solo las primeras cosas que me vienen a la mente. Esto es solo un ejemplo. Mi Visual Studio me dice que elem.data corresponde, en la vista de depuración, al [0]().

Ps. Olvídese de [0]().

+4

Los identificadores que comienzan con un guión bajo seguido de una letra mayúscula están reservados para la implementación. –

+3

No puedo imaginar que 'len = elem.data.size()' no falle si de alguna manera 'data' no se inicializa (lo que definitivamente debería ser). ¿Qué hay exactamente en 'data' y qué esperas que esté allí? – Jon

+1

Los elementos en el vector se construyen por defecto sobre un 'resize' (para un entero esto da como resultado 0) Para su clase personalizada, debe definir su propio constructor predeterminado. –

Respuesta

16

No, no llama al constructor del elemento predeterminado. std::vector nunca llama a los constructores predeterminados internamente (lo hace en C++ 11, pero no en versiones anteriores de la especificación).

La firma completa para vector::resize tiene el siguiente

void resize(size_type sz, T c = T()); 

es decir, tiene un segundo parámetro (con valor de argumento predeterminado). Ese segundo parámetro se usa luego como un objeto "fuente" para inicializar nuevos elementos mediante copy-constructor.

En otras palabras, su llamada a resize es en realidad equivalente a

vec.resize(9, _Struct()); 

que significa que es que que llamó al constructor por defecto cuando se suministra ese objeto "fuente" a vector::resize, a pesar de que no lo hiciste Notar eso.

Pero no todos los elementos del tipo _Struct se inicializan, especialmente el elemento de datos , que es otro std :: vector.

¿Huh? "No inicializado"? No sé lo que se supone que significa, teniendo en cuenta que en el código de muestra, cada nuevo elemento creado por resize se inicializa perfectamente como se describió anteriormente: se inicializa la copia desde un elemento _Struct() que se suministró implícitamente a resize como el segundo argumento. Cada _Struct::fval y _Struct::ival es cero, y cada _Struct::data es un vector vacío.

(En el original C++ 98 _Struct::fval y _Struct::ival permanecerán sin inicializar, ya pre-TC1 C++ 98 no apoyaron valor de inicialización. Pero _Struct::data se inicializa a un vector vacío incluso en el original C++ 98).

Me gustaría que se inicialice en el std :: vector vacío.

Cada _Struct::data vector ya se ha inicializado como vector vacío. ¿Qué te hizo creer que no es así?

P.S. Los nombres que comienzan con _ seguidos por una letra mayúscula están reservados por la implementación. No puedes usarlos.

+0

¿C++ 11 agrega una versión de emplazamiento de 'resize'? –

+0

@Kerrek SB: No veo una versión de emplazamiento allí, pero C++ 11 divide 'vector :: resize' en dos funciones: 1) solo tamaño y 2) tamaño y objeto" fuente ". La primera versión ahora realiza inicialización de valor internamente, lo que significa que mi respuesta no es completamente precisa para C++ 11 (aunque el resultado final es el mismo) – AnT

Cuestiones relacionadas