2012-04-11 13 views
7

Aquí es un código de ejemplo:¿Los contenedores que pasan por valor invalidan los iteradores?

#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); 
} 

En ideone la salida fue:

1 2 3 
163487776 2 3 

Preguntas

Si cambio f(T t)-f(T& t) la salida es como se esperaba. Asumo que porque estoy trabajando con copias de contenedores, técnicamente los iteradores que estoy presionando sobre el vector no son lo mismo que el vector que creé en main. ¿Es esto correcto? Lo único que noté es print(f(v)); imprime 1 2 3 como se esperaba, pero tan pronto como lo asigno a itervec, el primer iterador se convierte en basura, ¿todo esto depende de la implementación?

Respuesta

8

Sí, los iteradores son iteradores válidas sólo para el objeto local v en la función f, y al final de f, v sale del ámbito y se destruye, y los iteradores no son válidos.

Tiene que pasar el vector por referencia (o puntero o lo que sea) para que los iteradores que almacene sean los iteradores del objeto original que el llamador transfiere, no para una copia temporal almacenada en una variable local.

El comportamiento que está viendo no está definido, por lo que simplemente imprime los tres primeros y los dos últimos correctamente.

3

Sí, porque está recibiendo un iterador temporal y regresando de ese temporal. Después de salir de la función, el temporal se limpia, invalidando el iterador.

Si embargo te pasa una referencia tanto main y print están accediendo el mismo objeto. Como este objeto persiste después de la salida de la función, el iterador no se invalida.

Cuestiones relacionadas