2012-04-11 15 views
7

Ecco qualche esempio di codice:Il passaggio dei contenitori per valore invalida gli iteratori?

#include <iostream> 
#include <vector> 

template <typename T> 
std::vector<typename T::iterator> f(T t) 
{ 
     std::vector<typename T::iterator> v; 
     for (auto i = t.begin(); i != t.end(); ++i) 
     { 
       v.push_back(i); 
     } 
     return v; 
} 

template <typename T> 
void print(const std::vector<T>& v) 
{ 
     for (auto i = v.begin(); i != v.end(); ++i) 
     { 
       std::cout << **i << ' '; 
     } 
     std::cout << std::endl; 
} 

int main() 
{ 
     std::vector<int> v{1, 2, 3}; 
     print(f(v)); 
     std::vector<std::vector<int>::iterator> itervec = f(v); 
     print(itervec); 
} 

Sulla ideone l'uscita era:

1 2 3 
163487776 2 3 

Domande

Se cambio f(T t)-f(T& t) l'uscita è come previsto. Sto assumendo perché sto lavorando con copie di contenitori, tecnicamente gli iteratori che sto spingendo indietro sul vettore non sono gli stessi del vettore che ho creato in main. È corretto? L'unica cosa che ho notato è print(f(v)); stampe 1 2 3 come previsto, ma non appena lo assegno a itervec il primo iteratore diventa spazzatura, è tutta questa implementazione dipendente?

risposta

8

Sì, iteratori sono iteratori solo validi per l'oggetto locale v nella funzione f, e alla fine del f, v va fuori portata e viene distrutto, e gli iteratori non sono valide.

È necessario passare il vettore per riferimento (o puntatore o qualsiasi altra cosa) in modo che gli iteratori che si archiviano siano gli iteratori per l'oggetto originale passato dal chiamante, non per una copia temporanea archiviata in una variabile locale.

Il comportamento visualizzato non è definito, quindi accade solo di stampare correttamente i primi tre e gli ultimi due.

3

Sì, perché si riceve un temporaneo e si restituisce un iteratore temporaneo. Dopo l'uscita dalla funzione, il temporaneo viene ripulito, invalidando l'iteratore.

Se invece viene passato un riferimento sia main e print stanno accedendo lo stesso oggetto. Poiché questo oggetto persiste dopo l'uscita dalla funzione, l'iteratore non viene invalidato.

Problemi correlati