Reputation: 4095
Is it valid to call operator-- on an iterator that already points to the first element of the collection? Does the answer change for different collections (e.g. list vs vector vs set). E.g. see below
#include <algorithm>
#include <iostream>
#include <numeric>
#include <string>
#include <vector>
int main()
{
std::vector<int> v {1, 2, 4, 8, 16};
auto i=v.begin();
auto j=i;
--i; // not sure what's the effect of this
v.erase(j);
++i; // also not sure if this is not std::begin() anymore, what's the effect of ++
v.erase(i);
// Print vector.
std::for_each(v.begin(), v.end(), [](const int n) { std::cout << n << ' '; });
}
I suspect it's undefined behaviour but not quite sure.
Furthermore, what about removing elements from a std::list like below
std::list<int> v = { 1, 2, 3, 4, 5, 6 };
for (auto it = v.begin(); it != v.end(); it++)
{
v.erase(it--);
}
Upvotes: 2
Views: 240
Reputation: 5565
Let's take std::list
as an example, because essentially the same reasoning will apply to the other containers.
Looking at the member types of std::list
, we see that std::list::iterator
is a LegacyBidirectionalIterator. Checking the description there, we see the following precondition listed for operator--
to be valid:
Preconditions:
a
is decrementable (there exists suchb
thata == ++b
)
This is not the case for an iterator to the first element in a container, and indeed cppreference explicitly calls this out:
The begin iterator is not decrementable and the behavior is undefined if
--container.begin()
is evaluated.
Other containers like std::vector
use more expansive notions like LegacyRandomAccessIterator, but there's nothing there that changes the behavior of decrementing a begin iterator.
Upvotes: 3