Here is some example 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);
}
On ideone the output was:
1 2 3
163487776 2 3
Questions
If I change f(T t)
to f(T& t)
the output is as expected. I'm assuming because I am working with copies of containers, technically the iterators I am pushing back on the vector are not the same as the vector I created in main. Is this correct?
The one thing I noticed is print(f(v));
prints 1 2 3
as expected but as soon as I assign it to itervec
the first iterator becomes garbage, is this all implementation dependent?
An Iterator becomes invalidate when the container it points to changes its shape internally i.e. move elements from one location to another and the initial iterator still points to old invalid location. Iterator invalidation in vector happens when, An element is inserted to vector at any location.
Iterator Invalidation in C++ When the container to which an Iterator points changes shape internally, i.e. when elements are moved from one position to another, and the initial iterator still points to the old invalid location, then it is called Iterator invalidation. One should be careful while using iterators in C++.
To avoid invalidation of references to elements you can use a std::deque if you do not insert or erase in the middle. To avoid invalidation of iterators you can use a std::list.
std::sort will not invalidate iterators to a vector. The sort template uses the * operator on the iterators to access and modify the contents of the vector, and modifying a vector element though an iterator to an element already in the vector will not invalidate any iterators.
Yes, the iterators are iterators only valid for the local object v
in the function f
, and at the end of f
, v
goes out of scope and is destroyed, and the iterators are invalid.
You have to pass the vector by reference (or pointer or whatever) so that the iterators you store are the iterators for the original object that the caller passes in, not for a temporary copy stored in a local variable.
The behaviour you are seeing is undefined, so it just happens to print the first three and last two correctly.
Yes, because you are recieving a temporary and returning an iterator of that temporary. After function exit the temporary gets cleaned up, invalidating the iterator.
If you however get passed a reference both main
and print
are accessing the same object. Since this object persists after function exit the iterator is not invalidated.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With