Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove element in unordered_set using iterator in a loop

Please consider the following code:

Class MyClass is a self-defined class:

class MyClass
{
public:
    MyClass(int v) : Val(v) {}
    int Val;
};

Then the following code will cause Debug Assertion Failed in the loop just after calling it = T.erase(it);:

unordered_set<MyClass*> T;
unordered_set<MyClass*>::iterator it;

for (int i=0; i<10; i++)
    T.insert(new MyClass(i));

for (it = T.begin(); it != T.end(); it++)
{
    if ( (*it)->Val == 5 )
        it = T.erase(it); // After this line executes, in the next loop, the error occurs.
}

How to solve it and Why? PS: My environment: VS2010

like image 366
C. Wang Avatar asked Sep 06 '25 23:09

C. Wang


1 Answers

Suppose that the last element has Val = 5.

it = T.erase(it) is called, and it is set to T.end().

Then it++ is called, which causes an error because it is already set to end.

Essentially... when you erase an element in your current code, you end up double-advancing the iterator.

You could go with something like this instead....

for (it = T.begin(); it != T.end(); (*it)->Val == 5? it = T.erase(it) : ++it)
  ;
like image 101
QuestionC Avatar answered Sep 10 '25 01:09

QuestionC