I’m trying to figure out how std::multimap iterators work, therefore I’ve created a simple example that shows the substance of my problem. If uncomment case 1, I expect iterator to point to the first element with the key 1, but in reality it prints all the values associated with key 0 (like nothing was erased) and sometimes it crashes, probably because iterator is invalid. However if uncomment case 2, all the values with key 1 are properly deleted.
Is there any way to know what is the next valid iterator for the multimap after erasure?
(for example std::vector.erase(...) returns one)
std::multimap<int, int> m;
for(int j=0; j<3; ++j) {
for(int i=0; i<5; ++i) {
m.insert(std::make_pair(j, i));
}
}
for(std::multimap<int, int>::iterator it=m.begin(); it!=m.end();) {
printf("%d %d\n", (*it).first, (*it).second);
++it;
if( (*it).second == 3 ) {
//m.erase(0); //case 1
m.erase(1); //case 2
}
}
The cause of the problem
When you call
m.erase(0)in you example,itpoints at an element with the key0– soitis invalidated.m.erase(1)works, because when it is called the first time,itis not pointing to an element with the key1, so it is not affected. In later iterations, no elements with the key1remain, so nothing is deleted, and no iterator is affected.The Solution
multimapdoes not have anerase-method that returns the next valid iterator. One alternative is to callit = m.upper_bound(deleted_key);after the deletion. This is logarithmic, though, which might be too slow for your scenario (erase(x)andupper_boundwould be two logarithmic operations).Assuming you want to erase the key your iterator is currently pointing to, you could do something like this (otherwise,
eraseis fine, of course; not tested):This uses one linear operation, all the rest are constant time. If your map is very large, and you only have few items with equal keys, this will likely be faster. However, if you have many items with equal keys, the search for the end of the interval, is probably better done using
upper_bound(O(log n)instead ofO(n)when searching the end of the interval).