2012-04-11 17 views
7

Oto przykładowy kod:Czy przekazywanie kontenerów według wartości powoduje unieważnienie iteratorów?

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

Na ideone wyjście było:

1 2 3 
163487776 2 3 

Pytania

Jeśli zmienię f(T t) do f(T& t) wyjście jest zgodnie z oczekiwaniami. Zakładam, że pracuję z kopiami kontenerów, technicznie iteratory, które wypycham na wektorze, nie są tym samym, co wektor, który stworzyłem w main. Czy to jest poprawne? Jedną z rzeczy, którą zauważyłem, jest print(f(v)); drukuje 1 2 3 zgodnie z oczekiwaniami, ale tak szybko, jak przypisać do itervec pierwszy iterator staje się śmieci, czy to wszystko zależy od wykonania?

Odpowiedz

8

Tak, iteratory są iteratory ważne tylko dla lokalnego obiektu v w funkcji f, a na koniec f, v wychodzi z zakresu i jest niszczona, a iteratory są nieważne.

Musisz przekazać wektor przez referencję (lub wskaźnik lub cokolwiek innego), tak aby przechowywane iteratory były iteratorami dla oryginalnego obiektu, który odwiedzający wywołuje, a nie dla tymczasowej kopii przechowywanej w zmiennej lokalnej.

Zachowanie, które widzisz, jest niezdefiniowane, więc po prostu poprawnie drukuje pierwsze trzy i ostatnie dwa.

3

Tak, ponieważ otrzymujesz tymczasowy i zwrot iteratora tego tymczasowego. Po wyjściu funkcji tymczasowy zostaje oczyszczony, unieważniając iterator.

Jeśli jednak przejdzie odniesienie zarówno main i print uzyskiwania dostępu ten sam obiekt. Ponieważ obiekt ten występuje po zakończeniu funkcji, iterator nie jest unieważniany.

Powiązane problemy