1

For a unordered_map erase(), I have seen a few threads suggesting different methods for doing it (like getting the next element from the return of erase()). However, I haven't seen anybody suggesting the following. So, I was wondering if there is some issue with this approach:

for (auto it1 = map.begin(); it1 != map.end(); )
{
   auto it2 = it1++; //it2 assigned before it1 incremented
   map.erase(it2);
}
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
Prasanth
  • 11
  • 2
  • Why can't you just do `map.erase(it1);` ? – feverdreme Jan 12 '21 at 15:27
  • @feverdream this invalidates `it1` and the subsequent iteration of the loop would be undefined. The canonical way is `it1 = map.erase(it1)`. – Quentin Jan 12 '21 at 15:28
  • @feverdream because that would invalidate `it1` ? – Slava Jan 12 '21 at 15:28
  • There is nothing wrong with this method and it was suggested indeed for example https://stackoverflow.com/questions/263945/what-happens-if-you-call-erase-on-a-map-element-while-iterating-from-begin-to – Slava Jan 12 '21 at 15:31
  • 3
    Also correct is simply `map.erase(it1++);` No need for a second variable. You do have to understand that the iterator is incremented before erase is called, which is something that people do get confused about. – john Jan 12 '21 at 15:33
  • Great. Thanks Slava. Good to know there is no issue with this approach. – Prasanth Jan 12 '21 at 15:35
  • Thanks John. That's a good suggestion – Prasanth Jan 12 '21 at 15:37

1 Answers1

3

This approach works fine. std::unordered_map::erase only invalidates the iterator to the erased element (i.e. it2), the aforehand incremented iterator it1 remains valid.

References and iterators to the erased elements are invalidated. Other iterators and references are not invalidated.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405