在std :: set中使用erase 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 ?
}
}
}
答案 0 :(得分:41)
从标准23.1.2
插入成员不应影响迭代器和对容器的引用的有效性,并且擦除成员应仅使迭代器和对已擦除元素的引用无效。
修改
在你的情况下,itr2在擦除后失效,因此递增它会导致未定义的行为。在这种情况下,您可以关注reko_t建议,一般情况下,您可以尝试:
for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();)
{
classA *lt=(classA*)(*itr2);
li.erase(itr2++);
delete lt;
}
将增加迭代器之前从set中删除之前的值
BTW。 itr2不会被delete lt;
无效,而是li.erase(itr2);
答案 1 :(得分:7)
删除正常。
问题是你擦除 - 从而使itr2
无效,但是将它用于循环迭代。
i.a.w。在第一次擦除之后,++itr2
具有未定义的结果。
我在这种情况下使用的模式是:
while(itr2 != end())
{
iterator toDelete = itr2;
++itr2; // increment before erasing!
container.erase(toDelete);
}
一些非标准的STL impls有擦除返回下一个迭代器,所以你可以这样做:
while(itr2 != end())
itr2 = container.erase();
但是,这不是便携式的。
set<A*,B>
很奇怪 - 但在标准的impl中,B将是比较器。
答案 2 :(得分:2)
由于你只是显然删除了集合中的每个元素,你可以这样做:
for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();itr2++)
{
classA *lt=(classA*)(*itr2);
delete lt;
}
li.clear(); // clear the elements