2011-09-14 7 views
6

Sto provando il seguente codice:Il metodo vector.resize() chiama i costruttori di elementi predefiniti durante il ridimensionamento?

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]() 
    } 
} 

Il ridimensionamento (9) dovrebbe assegnare 9 elementi di tipo _Struct. E, in effetti funziona. Ma ogni elemento di tipo _Struct non è inizializzato, specialmente l'elemento data, che è un altro std :: vector. Mi piacerebbe che fosse inizializzato allo std :: vector vuoto. Devo farlo manualmente? Ho pensato che il metodo resize() avrebbe chiamato il costruttore predefinito di ogni elemento _Struct. Thx

Ps. I nomi delle strutture qui usate sono solo le prime cose che mi vengono in mente. Questo è solo un esempio. My Visual Studio mi informa che elem.data corrisponde, nella vista di debug, a [0]().

Ps. Dimentica il [0]().

+4

Gli identificatori che iniziano con un trattino basso seguito da una lettera maiuscola sono riservati per l'implementazione. –

+3

Non riesco a immaginare 'len = elem.data.size()' non si blocca se in qualche modo 'data' non è stato inizializzato (cosa che dovrebbe essere sicuramente). Cosa c'è esattamente in 'data' e cosa ti aspetti di essere lì dentro? – Jon

+1

Gli elementi nel vettore sono predefiniti costruiti su un 'ridimensionamento' (per un numero intero questo risulta in 0) Per la classe personalizzata, è necessario definire il proprio costruttore predefinito. –

risposta

16

No, non chiama il costruttore di elementi predefinito. std::vector non chiama mai internamente costruttori predefiniti (lo fa in C++ 11, ma non nelle versioni precedenti della specifica).

La firma completa per vector::resize si presenta come segue

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

Vale a dire ha un secondo parametro (con valore di argomento predefinito). Questo secondo parametro viene quindi utilizzato come oggetto "origine" per inizializzare nuovi elementi tramite copy-constructor.

In altre parole, il tuo invito resize è in realtà equivale a

vec.resize(9, _Struct()); 

che significa che è si che ha chiamato il costruttore di default quando si ha fornito dette oggetto "fonte" per vector::resize, anche se si didn non me ne accorgo.

Ma ogni elemento di tipo _Struct non è inizializzato, in particolare l'elemento di dati , che è un altro std :: vector.

Eh? "Non inizializzato"? Non so cosa dovrebbe significare, visto che nel tuo codice di esempio ogni nuovo elemento creato da resize è perfettamente inizializzato come descritto sopra: è inizializzato da una copia da un elemento _Struct() che hai implicitamente fornito a resize come secondo argomento. Ogni _Struct::fval e _Struct::ival è zero e ogni _Struct::data è un vettore vuoto.

(In originale C++ 98 _Struct::fval e _Struct::ival rimarrà inizializzata dal pre-TC1 C++ 98 non hanno sostenuto valore di inizializzazione. Ma _Struct::data sarà inizializzata ad un vettore vuoto anche in originale C++ 98).

Vorrei che fosse inizializzato allo std :: vector vuoto.

Ogni vettore _Struct::data è già inizializzato come vettore vuoto. Cosa ti ha fatto credere che non lo sia?

P.S. I nomi che iniziano con _ seguiti da una lettera maiuscola sono riservati dall'implementazione. Non sei autorizzato a usarli.

+0

Il C++ 11 aggiunge una versione emplacing di 'ridimensiona'? –

+0

@Kerrek SB: Non vedo una versione emplacing lì, ma C++ 11 divide 'vector :: resize' in due funzioni: 1) solo dimensione e 2) dimensione e oggetto" sorgente ". La prima versione ora esegue internamente l'inizializzazione del valore, il che significa che la mia risposta non è completamente precisa per C++ 11 (anche se il risultato finale è lo stesso) – AnT

Problemi correlati