c++stliteratorunordered-mapunordered-multimap

Unordered_mutlimap iterator erase


I have the following code

#include <iostream>
#include <unordered_map>

using namespace std;

int main()
{
    unordered_multimap<int, int> uomap;
    typedef unordered_multimap<int, int>::iterator iter;

    uomap.insert({ 2, 30 });
    uomap.insert({ 1, 40 });
    uomap.insert({ 3, 60 });
    uomap.insert({ 2, 20 });
    uomap.insert({ 5, 50 });

    for (auto iter = uomap.begin(); iter != uomap.end(); iter++)
        cout << iter->first << " " << iter->second << "\n";
    cout << "\n";

    int k = 0;
    for (auto iter = uomap.begin(); iter != uomap.end(); iter++)
    {
        if (k % 2 == 0)
        auto it = uomap.find(it);
        uomap.erase(it);
        k++;
    }
    
    /*
    auto it1 = uomap.find(2);
    uomap.erase(it1);
    */

    for (auto iter = uomap.begin(); iter != uomap.end(); iter++)
        cout << iter->first << " " << iter->second << "\n";
    cout << "\n";

    return 0;
}

And my issue would be in line 26 where I have a compiling issue. According to VisualStudio identifier "it" is undefined, but if I were to write the same thing outside of a "for" like in the commented section, the code would run just fine.

Basically I'm testing different ways of getting elements out of an unordered_multimap for another problem I have, but I just can't seem to get things to work. Can anyone enlighten me? Thanks a bunch.


Solution

  • Deleting all the even elements from an unordered_map

    for (auto it = uomap.begin(); it != uomap.end(); )
    {
        if (it->first % 2 == 0)
            it = uomap.erase(it);
        else
            ++it;
    }
    

    This the standard technique, the key part is that you do not increment the iterator when you do the erase, instead the return value from erase is the new iterator value. This is because erasing an element from a map also invalidates any iterator pointing to that element. Any operation on an invalidated iterator causes undefined behaviour, even just incrementing it. Conveniently though the erase method returns the next iterator.