3

Possible Duplicate:
How to filter items from a std::map?
What happens if you call erase() on a map element while iterating from begin to end?

I have map of objects and i want to iterate over it and remove some entries.

typedef std::map<A,B> MapT;
MapT m;
MapT::iterator it;

for(it = m.begin(); it != m.end(); it++ ) {
    if( condition ) m.erase(it);
}

Can I do it in this way?

Community
  • 1
  • 1
kravemir
  • 10,636
  • 17
  • 64
  • 111
  • The iterator will be invalidated once you modify the map. – Joe May 09 '12 at 17:06
  • 1
    See [here](http://stackoverflow.com/questions/263945/what-happens-if-you-call-erase-on-a-map-element-while-iterating-from-begin-to). (duplicate) – TaZ May 09 '12 at 17:09

2 Answers2

8

In case of std::map iterators and references to the erased elements are invalidated [23.1.2/8]. Your code uses the iterator after it has been invalidated, this results in an Undefined Behavior. In order to avoid this Undefined behavior the iterator needs to be incremented before it gets invalidated in the erase() call.

You need to use:

for(it = m.begin(); it != m.end(); ) {
    if( condition )
        m.erase(it++);
    else
        ++it;
}

Note that here it++ increments it so that it refers to the next element but yields a copy of its original value. Thus, it doesn't refer to the element that is removed when erase() is called.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
2

Assuming MapT is a std::map, then the iterator will be invalidated when erased. The correct way to do this (erase in a loop) is to cache the iterator and increment prior to erasing it:

MapT m;
MapT::iterator it;

for(it = m.begin(); it != m.end();)
{
    if(condition)
    {
       MapT::iterator tmp = it++;
       m.erase(tmp);
    }
    else
    {
       ++it;
    } 
}
Chad
  • 18,706
  • 4
  • 46
  • 63