2

Found this (simplified version below) in some old code and the Debugger (VC++ 2015) did not complain about an invalid iterator while executing it.

#include <iterator>
#include <set>
int main() {
    std::set<int> s = {0,1,2,3,4};
    auto it = std::begin(s);
    while (it != std::end(s))
    {
        if (*it % 2 == 0)
            s.erase(it++); // UB?
        else
            ++it;
    }
}

I know it should be it = s.erase(it); instead, but I was wondering if this actually is undefined behaviour. Is it, or is there something going on that renders the code OK?

The documentation says "References and iterators to the erased elements are invalidated. Other references and iterators are not affected.""

The following would of course be undefined:

s.erase(it);
++it

And the now following would be OK:

auto temp = it;
++temp;
s.erase(it);
it = temp;

But what about my code above?

s.erase(it++);
Tobias Hermann
  • 9,936
  • 6
  • 61
  • 134
  • 2
    Its fine. Unlike a vector only the current iterator is invalidated. – NathanOliver Jan 18 '17 at 18:17
  • 1
    According to [the doc](http://en.cppreference.com/w/cpp/container/set/erase) only iterators to the element being erased are invalidated, any other is fine. (and since post-incr returns the non-incremented value...) – Borgleader Jan 18 '17 at 18:18
  • Thanks for the quick responses. Sill I have a question left. Just edited my post accordingly. – Tobias Hermann Jan 18 '17 at 18:22
  • `it++` gives you two different iterators. The function gets what the iterator was before incrementing and the loop has the next iterator. It basically does what your OK example does. – NathanOliver Jan 18 '17 at 18:25
  • Great. Thank you Nathan. – Tobias Hermann Jan 18 '17 at 18:29
  • OK, and by implementing a dummy-version of operator++ I also understand why the code is equivalent to the OK version: http://ideone.com/UWOsFq – Tobias Hermann Jan 19 '17 at 10:07

0 Answers0