This sample program gets an iterator to an element of a vector contained in another vector. I add another element to the containing vector and then print out the value of the previously obtained iterator:
#include <vector>
#include <iostream>
int main(int argc, char const *argv[])
{
std::vector<std::vector<int> > foo(3, std::vector<int>(3, 1));
std::vector<int>::iterator foo_it = foo[0].begin();
std::cout << "*foo_it: " << *foo_it << std::endl;
foo.push_back(std::vector<int>(3, 2));
std::cout << "*foo_it: " << *foo_it << std::endl;
return 0;
}
Since the vector correspinding to foo_it
has not been modified I expect the iterator to still be valid. However when I run this code I get the following output (also on ideone):
*foo_it: 1
*foo_it: 0
For reference I get this result using g++ versions 4.2 and 4.6 as well as clang 3.1. However I get the expected output with g++ using -std=c++0x
(ideone link) and also with clang
when using both -std=c++0x
and -stdlib=libc++
.
Have I somehow invoked some undefined behavior here? If so is this now defined behavior C++11? Or is this simply a compiler/standard library bug?
Edit I can see now that in C++03 the iterators are invalidated since the vector's elements are copied on reallocation. However I would still like to know if this would be valid in C++11 (i.e. are the vector's elements guaranteed to be moved instead of copied, and will moving a vector not invalidate it's iterators).
push_back
invalidates iterators, simple as that.
std::vector<int>::iterator foo_it = foo[0].begin();
foo.push_back(std::vector<int>(3, 2));
After this, foo_ti
is no longer valid. Any insert/push_back has the potential to internally re-allocate the vector.
Since the vector correspinding to
foo_it
has not been modified
Wrong. The push_back
destroyed the vector corresponding to foo_it
. foo_it
became invalid when foo[0]
was destroyed.
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