Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

semantics of end() iterator for vector and list

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)?

like image 963
petersohn Avatar asked Jul 05 '13 16:07

petersohn


1 Answers

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.

like image 65
James Kanze Avatar answered Oct 08 '22 01:10

James Kanze