According to the C++ standard, calling push_back()
on a vector invalidates the iterator if the new size of the vector grows above its capacity, but on a list it never invalidates iterators. Now consider the following code snippets:
1.
vector<int> v{1,2,3};
v.reserve(100);
for (int i: v) {
v.push_back(i);
}
2.
list<int> l{1,2,3};
for (int i: l) {
l.push_back(i);
}
I tried it with gcc 4.8 and found that code 1 finishes with v
being {1,2,3,1,2,3}
, but code 2 runs into an infinite loop. The explanation seems pretty simple to me: the end()
iterator of vector
points to a memory location, and since it is only evaluated once during a range based for loop, it stops when it reaches past the 3rd element of the vector. On the other hand, list
probably has some kind of null token as an end iterator, which is always placed after the last element, thus the loop will never reach it.
While the results seem straightforward, my question is what does the standard say about this? Is it supposed to be so in every standard library implementations, or is this behavior not defined? What should I expect when writing a loop that may call push_back()
to such a container (which I usually like to avoid anyway)?
I don't think that the standard is very explicit, but in
general, end
means end
, and if you insert elements beyond
the current position in a loop, you'll never get there.
Of course, your first loop, with vector
, has undefined
behavior, since insert (and erase) invalidates all iterators at
or beyond the position of the insertion, even if there is no
reallocation. And the end iterator will always be beyond the
point of insertion.
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