2010-02-02 18 views
6

La mia domanda è semplice. Quando uso i contenitori STL, copiano il valore che immagazzino lì (usando il costruttore di copie) o no? Cosa succede se do loro una matrice di caratteri (char *) invece di un'istanza di stringa? Come si comportano? È garantito che le informazioni verranno archiviate nell'heap anziché nello stack di sistema?Comportamento contenitori C++

Grazie per le risposte.

risposta

7

I valori nei contenitori STL sono memorizzati in base al valore. Se si dispone di un vettore come questo:.

class BigObject 
{ 
... 
}; 

vector<BigObject> myObjs; 
myObjs.push_back(obj1); 
myObjs.push_back(obj2); 
... 

Il vettore farà una copia dell'oggetto si sta spingendo nella Anche nel caso di un vettore, può fare nuove copie tardi quando deve riallocare la memoria sottostante, quindi tienilo a mente.

La stessa cosa è vera quando si dispone di un vettore di puntatori, come vector<char*> - ma la differenza è che il valore che è copie è il puntatore, non la stringa a cui punta. Quindi, se si dispone di:

vector<char*> myStrings; 
char* str = new char[256];  // suppose str points to mem location 0x1234 here 
sprintf(str, "Hello, buffer"); 
myStrings.push_back(str); 
delete [] str; 

... il vettore otterrà una copia del puntatore. Il puntatore che ottiene avrà lo stesso valore (0x1234), e dal momento che tu hai delete d quel puntatore dopo aver premuto il puntatore, il tuo vettore contiene un puntatore jolly e il tuo codice finirà per bloccarsi (prima o poi, si spera).

Il che, tra l'altro, si sarebbe potuto evitare se invece di utilizzare char * s voi stringhe utilizzate:

typedef vector<string> strings; 
strings myStrings; 
myStrings.push_back("Hello, buffer"); 
5

Copia il valore. La maggior parte dei container (tutti?) Richiede che siano definiti un costruttore di copie e un operatore di assegnazione.

Se si dà loro un char*, si copia il puntatore, non il valore indicato. Quindi, sarebbe tua responsabilità assicurarti che la stringa stessa non venga distrutta mentre è ancora in uso, e venga distrutta quando non è più necessaria.

+0

Per essere chiari, i contenitori copiano il valore del tipo di argomento del modello di elemento. Se il contenitore è definito per contenere "int *", copierà i puntatori agli interi, non agli interi sottostanti. –

3

Fanno sempre delle copie. Se si crea un vector<char *>, verrà copiato lo char* inserito. Tuttavia, non copierà la stringa di caratteri a cui punta il puntatore. Se questa stringa è stata allocata dinamicamente, probabilmente c'è una perdita, motivo per cui vector<string> è in genere infinitamente preferibile.

1

Vengono sempre copiati quando li inserisci. Se gli dai un puntatore, allora copiano il puntatore. I dati a cui punta il puntatore non sono influenzati. Nota, non è consigliabile mettere i puntatori grezzi in contenitori stl, perché è facile perdere traccia di loro e perdita di memoria. I contenitori STL non sono stati progettati per aiutarti con i puntatori grezzi. Se si desidera utilizzare i puntatori nei contenitori STL, considerare shared_ptr da boost per racchiuderli.

1

Hai già ottenuto un certo numero di risposte sottolineando che quando si mette i dati in un contenitore, è messo lì per valore, quindi ciò che entra nel contenitore è una copia dei tuoi dati originali.

Esiste tuttavia un'eccezione a questa regola: std::list ha un membro splice che consente di inserire una parte (o tutti) di una lista in un'altra lista. In questo caso, i dati vengono normalmente spostati anziché copiati - almeno normalmente, lo splicing viene eseguito manipolando i puntatori, in modo che i nodi presenti in un elenco vengano trapiantati nell'altro elenco.

L'eccezione è se i due elenchi utilizzano tipi di allocatore diversi.In questo caso, credo che la giuntura debba allocare nuovi nodi, copiare dati, quindi rilasciare i vecchi nodi. Quindi, di nuovo, questo è un caso d'angolo abbastanza oscuro: la maggior parte delle persone non implementa mai i propri tipi di allocatore.

0

Inoltre, se non si desidera il sovraccarico di copiare interi oggetti e non si apprezza il mal di testa associato all'uso dei puntatori, è possibile utilizzare boost :: shared_ptr all'interno di un vettore per garantire che la memoria allocata dinamicamente venga rilasciata solo quando non viene più referenziato.