2009-09-05 8 views
12

Sono sempre stato un po 'confuso su come i valori STL dei contenitori (vettore, elenco, mappa ...). Memorizzano riferimenti ai valori che ho inserito, oppure copiano/copiano costrutto + memorizzano i valori stessi?STL: memorizza riferimenti o valori?

Per esempio,

int i; 
vector<int> vec; 
vec.push_back(i); 
// does &(vec[0]) == &i; 

e

class abc; 
abc inst; 
vector<abc> vec; 
vec.push_back(inst); 
// does &(vec[0]) == &inst; 

Grazie

+5

Hai quello che mi sembra un codice funzionante che testerebbe la risposta (con una piccola modifica per rendere il commento un condizionale). Eseguilo e guarda! Sono abbastanza sicuro che copiano, costruiscono e archiviano però. –

risposta

18

contenitori STL copy-costruire i valori e memorizzare che si passa. Se si desidera memorizzare gli oggetti in un contenitore senza copiandoli, suggerirei di memorizzare un puntatore sull'oggetto nel contenitore:

class abc; 
abc inst; 
vector<abc *> vec; 
vec.push_back(&inst); 

Questo è il modo più logico per implementare le classi contenitore per impedire la memorizzazione accidentale di riferimenti a variabili su frame di stack defunti. Considerate:

class Widget { 
public: 
    void AddToVector(int i) { 
     v.push_back(i); 
    } 
private: 
    vector<int> v; 
}; 

Memorizzazione di un riferimento alla i sarebbe pericoloso come si sarebbe fa riferimento la posizione in memoria di una variabile locale dopo il ritorno dal metodo in cui è stata definita.

+5

Non è possibile creare contenitori di creazione che memorizzino riferimenti in C++. L'argomento di tipo passato al contenitore deve essere assegnabile. I riferimenti non sono assegnabili, sono inizializzati con un oggetto ma non possono essere assegnati a un oggetto diverso dopo la costruzione. Pertanto, i tipi di riferimento non soddisfano i requisiti del tipo da utilizzare all'interno dei contenitori. Se vuoi avere la stessa semantica (o il più vicino possibile) devi fornire un wrapper di riferimento (boost :: ref/boost :: cref) –

+3

@dribeas: questa risposta spiega _why not_, spiegando i rischi di un'ipotetica implementazione. – MSalters

4

Dipende dal tipo. Se si tratta di un tipo di valore semplice, ed economico da copiare, quindi la memorizzazione dei valori è probabilmente la risposta. D'altra parte, se si tratta di un tipo di riferimento, o costoso da copiare, è meglio memorizzare un puntatore intelligente (non auto_ptr, poiché la sua speciale semantica della copia ne impedisce l'archiviazione in un contenitore. Con un semplice puntatore si rischia la perdita di memoria e l'accesso alla memoria liberata, mentre con i riferimenti si rischia il secondo. Un puntatore intelligente evita entrambi.

+2

+1 sull'uso di puntatori intelligenti all'interno dei contenitori per gestire la memoria. Un'altra scelta potrebbe essere l'utilizzo di una libreria come Boost Pointer Container per occuparsi della deallocazione delle risorse –

+5

Questo non è ciò che l'OP sta chiedendo. Vuole sapere se le classi contenitore stesse copiano il valore quando viene inserito nel contenitore. La risposta è, sì, lo fanno - motivo per cui la memorizzazione dei puntatori può essere buona se il particolare tipo in questione è costoso da copiare. –

+2

E la memorizzazione di puntatori nudi va perfettamente bene se sai cosa stai facendo e ripulisci dopo di te. –