Keeping it low-key this week, let's re-iterate (lol) the conventional map-erase idiom in C++.
Iterating through the elements of a
std::map is easy enough, but complication arises when you want to delete a few elements as you go.
The first naive approach might look a little like this:
Unfortunately, after you've erased the element from the map, the iterator pointing to it is invalidated. When the loop goes to run
++it ready for the next iteration, this invokes UB… meaning you should never do it. It's invalid.
So what to do? If you do
++it before performing the erase, then it's safe, but then you don't have the iterator to erase any more. You can use a copy:
Note the important change to the for declaration. The increment on each loop is replaced by the conditional increment in the body.
A shorter version of the same thing is:
This works because
it++ inherently makes a copy, performing the increment after the original value is sent to
erase, but before the erase actually occurs.
Other standard containers make this a lot easier; the next C++ standard, due for completion this year (or possibly in 2012), will fix this omission for
std::map by allowing
m.erase to return the next iterator automatically: