lwxted
lwxted

Reputation: 2429

Can we safely rely on the location of v.end() of iterators?

For a vector v in STL, is it safe to store v.end() (eg. vector::iterator) for later use? Will I be guaranteed that when I later use the stored iterator, it will still point at the same location?

Consider the following vector v:
1, 2, 3, 4, 5

I now store away std::vector<int>::iterator it = v.end(). Later, I push in 2 new elements into the vector, after which it looks like:
1, 2, 3, 4, 5, 6, 7.

Can I now be assured that *it == 6?

Upvotes: 2

Views: 98

Answers (2)

Mooing Duck
Mooing Duck

Reputation: 66952

§ 23.3.6.5/1 [vector.modifiers]

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.

It's not stated explicitly, but this means that all iterators, references at and after the insertion point are invalidated. This includes the end iterator. This section is specifically about insert/push_back, but is still more or less accurate when it comes to erases and such as well.

§ 23.3.6.3/5 [vector.capacity]

Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence. It is guaranteed that no reallocation takes place during insertions that happen after a call to reserve() until the time when an insertion would make the size of the vector greater than the value of capacity().

Upvotes: 1

Martin Drozdik
Martin Drozdik

Reputation: 13313

No.

After you push something into a std::vector the end() iterator is always invalidated.

All other iterators are valid unless

the new container size is greater than the previous capacity


However there are containers whose iterators do not get invalidated after pushing. Refer to the excellent answers to this question.


If you want to remember the locations within a vector using iterators while pushing new elements, you can ensure that the new size is not greater than the old capacity using the reserve() member.

std::vector<int> numbers = {1,2,3};
numbers.reserve(4);
int capacity = numbers.capacity();  // capacity >= 4
std::vector<int>::iterator pos = numbers.begin() + 2 // any iterator before
                                                     // the point of insertion
numbers.push_back(4); // new size is 4, old capacity is >= 4, 
                      // therefore pos is still valid. 

Upvotes: 6

Related Questions