在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 ?
}
}
}
Run Code Online (Sandbox Code Playgroud)
Tad*_*pec 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;
}
Run Code Online (Sandbox Code Playgroud)
这将在从set中删除之前的值之前递增迭代器.
BTW.itr2不会失效delete lt;
,而是通过li.erase(itr2);
删除没问题.
问题是你擦除 - 从而使其无效 - itr2
但是将它用于循环迭代.
在第一次擦除之后,它++itr2
具有未定义的结果.
我在这种情况下使用的模式是这样的:
while(itr2 != end())
{
iterator toDelete = itr2;
++itr2; // increment before erasing!
container.erase(toDelete);
}
Run Code Online (Sandbox Code Playgroud)
一些非标准的STL impls有擦除返回下一个迭代器,所以你可以这样做:
while(itr2 != end())
itr2 = container.erase();
Run Code Online (Sandbox Code Playgroud)
但这不是便携式的.
的set<A*,B>
是陌生的,虽然-在一个标准的IMPL,B是比较.
由于您显然只是删除了集合中的每个元素,因此您可以这样做:
for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();itr2++)
{
classA *lt=(classA*)(*itr2);
delete lt;
}
li.clear(); // clear the elements
Run Code Online (Sandbox Code Playgroud)