Итератор, после вызова erase() в std:: set

Удалить стереть вызов в std:: set invalidate iterator? Как я сделал ниже 5-го из последней строки..? если да, то лучший способ стереть все элементы из набора

class classA
{
public:
    classA(){};
    ~classA(){};
};
struct structB
{
};

typedef std::set <classA*, structB> SETTYPE;        
typedef std::map <int, SETTYPE>MAPTYPE;

int __cdecl wmain (int argc, wchar_t* pArgs[])
{
    MAPTYPE mapObj; 
    /*
      ...
      ..   Some Operation Here
      ...
      */
    for (MAPTYPE::iterator itr1=mapObj.begin(); itr1!=mapObj.end(); itr1++) 
    {       
        SETTYPE li=(*itr1).second;
        for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();itr2++) 
        {
            classA *lt=(classA*)(*itr2);
            li.erase(itr2); 
            delete lt; // Does it invalidate Iterator ?
        }
    }
}

Ответ 1

Поскольку вы просто, по-видимому, удаляете каждый элемент набора, вы можете просто сделать:

    for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();itr2++) 
    {
            classA *lt=(classA*)(*itr2);
            delete lt;
    }
    li.clear(); // clear the elements

Ответ 2

Из стандарта 23.1.2

Элементы вставки не должны влиять на действительность итераторов и ссылок на контейнер, а члены стирания делают недействительными только итераторы и ссылки на стертые элементы.

ИЗМЕНИТЬ

В вашем случае itr2 недействителен после стирания, поэтому приращение приводит к поведению undefined. В этом случае вы можете следовать совету reko_t, в общем, вы можете попробовать следующее:

for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();) 
{
    classA *lt=(classA*)(*itr2);
    li.erase(itr2++); 
    delete lt;
}

который увеличит итератор до, удалив его из предыдущего значения. КСТАТИ. itr2 не отменяется delete lt;, но li.erase(itr2);

Ответ 3

Удаление - это нормально.

Проблема заключается в том, что вы удаляете - и, следовательно, недействительны - itr2, но используете его для итерации цикла.

i.a.w. после первого удаления ++itr2 имеет undefined результаты.

Образец, который я использую в этой ситуации, таков:

while(itr2 != end())
{
   iterator toDelete = itr2;
   ++itr2;   // increment before erasing!
   container.erase(toDelete);
}

Некоторые нестандартные скрипты STL стирают возвратный следующий итератор, поэтому вы можете сделать:

while(itr2 != end())
   itr2 = container.erase();

но не переносимый.


set<A*,B> странно, хотя - в стандартном impl, B будет компаратором.