user393964
user393964

Reputation:

Remove only one element from multimap with duplicate keys

I have a multimap with Note objects from which I want to remove only one object. There can be several Note objects with the same key. The problem is that right now there's also objects being removed that aren't within the key range I specify:

long key = note.measureNumber * 1000000 + note.startTime; // = 2000001
multimap<long, Note>::iterator it;
for (it = noteList.lower_bound(key); it != noteList.end() && it->first < (key + 1); it++) {
    if(it->second.frequency == note.frequency){
        noteList.erase(it);
    }
}

When I run this code with key 2000001 the object I'm able to erase the right object, but another object with key 1000017 gets erased as well. Both objects have the same frequency though.

Any idea's what is wrong with my for loop?

EDIT: To be clear, I only want to check for objects with one specific key (in this case 2000001) there's no need for the iterator to look at objects with different keys than that one.

Upvotes: 4

Views: 3729

Answers (3)

Alex I.
Alex I.

Reputation: 1

As already indicated here, erasing an iterator invalidates it. I'd like to point out some inefficiency in code you have: You don't need to iterate till the end of the loop. Consider this:

for (it = noteList.lower_bound(key); it != noteList.upper_bound(key) && it->first == key; it++)
{
    if(it->second.frequency == note.frequency)
    {
       noteList.erase(it++);
    }
    else
    {
        ++it;
    }
}

Upvotes: 0

Craig H
Craig H

Reputation: 7989

Once you erase an iterator it becomes invalid. If you wish to erase from a map while you iterate through it, your code needs to change. Try this:

multimap<long, Note>::iterator it;
for (it = noteList.lower_bound(key); it != noteList.end() && it->first < (key + 1);) {
    if(it->second.frequency == note.frequency){
        noteList.erase(it++);
    }
    else
    {
        ++it;
    }
}

Upvotes: 1

Rob Walker
Rob Walker

Reputation: 47462

Calling erase() with the iterator will invalidate it, so you can't then continue to use it.

See Can I continue to use an iterator after an item has been deleted from std::multimap<>

Upvotes: 2

Related Questions