tags:

views:

618

answers:

2

Can I continue to use an multimap iterator even after a call to multimap::erase()? For example:

Blah::iterator iter;
for ( iter = mm.begin();
      iter != mm.end();
      iter ++ )
{
    if ( iter->second == something )
    {
        mm.erase( iter );
    }
}

Should this be expected to run correctly, or is the iterator invalidated following the call to erase? Reference sites like http://www.cplusplus.com/reference/stl/multimap/erase.html are strangely quiet on this topic of the lifespans of iterators, or the effects of constructive/destructive methods on iterators.

A: 

C++ Standard 23.1.2.8:

The insert members shall not affect the validity of iterators and references to the container, and the erase members shall invalidate only iterators and references to the erased elements.

This is a common requirement for all associative containers, and std::multimap is one of them.

Igor Semenov
Did you notice that iter++ is called *after* iter has been invalidated? Are you sure that the standard explicitly permits this?
Andreas Huber
Of course not. Standard guarantees, that all iterators except those which point to erased elements, are correct.
Igor Semenov
In this case, a direct answer to the OPs question would probably have earned you more rep...
Andreas Huber
+9  A: 

http://www.sgi.com/tech/stl/Multimap.html

Multimap has the important property that inserting a new element
into a multimap does not invalidate iterators that point to existing
elements. Erasing an element from a multimap also does not invalidate
any iterators, except, of course, for iterators that actually point to
the element that is being erased.

So it should look like this:

Blah::iterator iter;
for ( iter = mm.begin();iter != mm.end();)
{
    if ( iter->second == something )
    {
        mm.erase( iter++ );
        // Use post increment. This increments the iterator but
        // returns a copy of the original iterator to be used by
        // the erase method
    }
    else
    {
        ++iter;   // Use Pre Increment for efficiency.
    }
}

Also see: http://stackoverflow.com/questions/263945/what-happens-if-you-call-erase-on-a-map-element-while-iterating-from-begin-to-e

and

http://stackoverflow.com/questions/268898/delete-a-specific-entry-in-the-map-but-the-iterator-must-point-to-the-next-elemen#269717

Martin York
Sorry to question you, but the post-increment of the iter doesn't result in an increment of an iterator that has now been invalidated? I see your commented block at lines 7-9, but must admit I didn't know this.
Stéphane
Question as much as possable:-)
Martin York
From the draft standard (n2521) Section 5.2.6: Increment and decrement. The value of a postfix ++ expression is the value of its operand. [ Note: the value obtained is a copy of the original value — end note ]
Martin York
Note that all arguments to methods/functions must be fully evaluated before the method/function is called. So the above works.
Martin York