Does skipping containers by value invalidate iterators?

Here is a sample code:

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

In ideone, the output was:

 1 2 3 163487776 2 3 

Questions

If I change f(T t) to f(T& t) , the output will be as expected. I guess, because I work with copies of containers, technically the iterators that I return back to the vector do not match the vector that I created mostly. It's right? The only thing I noticed is print(f(v)); prints 1 2 3 as expected, but as soon as I assign it itervec , the first iterator will become garbage, does it depend on the implementation?

+7
source share
2 answers

Yes, iterators are iterators that are valid only for the local object v in the function f , and at the end of f , v goes beyond the scope and is destroyed, and iterators are invalid.

You must pass the vector by reference (or a pointer or something else) so that the iterators you store are iterators of the original object that the caller passes, and not for a temporary copy stored in a local variable.

The behavior you see is undefined, so it’s just right to type the first three and last two.

+8
source

Yes, because you get a temporary one and return an iterator of that temporary one. After exiting the function, temporary cleaning, canceling the iterator.

If you, however, passed the link, both main and print , refer to the same object . Since this object is saved after the function exits, the iterator is not invalid.

+3
source

All Articles