在std :: set中擦除()之后的迭代器有效性

Sat*_*bir 10 c++ stl 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 ?
        }
    }
}
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);

  • 由于这回答了我的谷歌"确实设置擦除无效迭代器",这是我最喜欢的答案 (3认同)

pet*_*hen 7

删除没问题.

问题是你擦除 - 从而使其无效 - 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是比较.


rek*_*o_t 2

由于您显然只是删除了集合中的每个元素,因此您可以这样做:

    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)