Итератор, после вызова 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 будет компаратором.