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)?
vector, it is because there is undefined behavior, so anything the implementation does is legal.)§23.3.6.5/1: "Remarks: Causes reallocation if the new size is greater than the old capacity. If no reallocation happens, all the iterators and references before the insertion point remain valid."