Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does vector::pop_back invalidate the iterator (end() - 1)?

Note: The question applies to erase, too. See bottom.


What's the reason behind the fact that the end() - 1 iterator is invalidated after pop_back is called on a vector?

To clarify, I'm referring to this situation:

std::vector<int> v;
v.push_back(1);
v.push_back(2);

std::vector<int>::iterator i1 = v.begin(), i2 = v.end() - 1, i3 = v.begin() + 1;

v.pop_back();

// i1 is still valid
// i2 is now invalid
// i3 is now invalid too

std::vector<int>::iterator i4 = v.end();

assert(i2 == i4);  // undefined behavior (but why should it be?!)
assert(i3 == i4);  // undefined behavior (but why should it be?!)

Why does this happen? (i.e. when would this invalidation ever prove beneficial for the implementation?)

(Note that this isn't just a theoretical problem. Visual C++ 2013 -- and probably 2012 too -- display an error if you try to do this in debug mode, if you have _ITERATOR_DEBUG_LEVEL set to 2.)


Regarding erase:

Note that the same question applies to erase:
Why does erase(end() - 1, end()) invalidate end() - 1?

(So please don't say, "pop_back invalidates end() - 1 because it is equivalent to calling erase(end() - 1, end())"; that's just begging the question.)

like image 320
user541686 Avatar asked Jul 22 '13 01:07

user541686


People also ask

Why are iterators invalidated?

All iterators and the references are invalidated if the inserted item is not inserted at the end of the deque. If the items are deleted from any of the position except the end position, then all iterators will be invalidated. Same as like insert or erase.

What invalidates an iterator?

When the container to which an Iterator points changes shape internally, i.e. when elements are moved from one position to another, and the initial iterator still points to the old invalid location, then it is called Iterator invalidation. One should be careful while using iterators in C++.

What does vector Pop_back do?

pop_back() function is used to pop or remove elements from a vector from the back. The value is removed from the vector from the end, and the container size is decreased by 1.

How does Pop_back work in C++?

The list::pop_back() is a built-in function in C++ STL which is used to remove an element from the back of a list container. That is, this function deletes the last element of a list container. This function thus decreases the size of the container by 1 as it deletes an element from the end of list.


1 Answers

The interesting question is really what does it mean for an iterator to be invalidated. And I truly don't have a good answer from the standard. What I do know is that to some extent the standard considers an iterator not as a pointer to a location inside the container, but rather as a proxy to a particular element that lives within the container.

With that in mind, after erasing of a single element in the middle of a vector, all iterators after the point of removal become invalidated as they no longer refer to the same element that they referred to before.

Support for this line of reasoning comes from the iterator invalidation clauses of other operations in the container. For example, on insert, the standard guarantees that if there is no reallocation the iterators before the point of insertion remain valid. Exceptio probat regulam in casibus non exceptis, it invalidates all iterators after the point of insertion.

If the validity of iterators was only related to the fact that there is an element of the container where the iterator points, then none of the iterators would be invalidated with that operation (again, in the absence of reallocations).

Going even further in that line of reasoning, if you consider iterator validity as pointer validity, then none of the iterators into a vector would be invalidated during an erase operation. The end()-1 iterator would become non-dereferencable, but it could remain valid, which is not the case.

like image 155
David Rodríguez - dribeas Avatar answered Oct 17 '22 02:10

David Rodríguez - dribeas