C++ 在std::set中的erase()调用之后,迭代器的有效性

C++ 在std::set中的erase()调用之后,迭代器的有效性,c++,stl,set,C++,Stl,Set,在std::set invalidate迭代器中执行擦除调用吗?正如我在最后一行的第5行下面所做的。。? 如果是,有什么更好的方法从集合中删除所有元素 class classA { public: classA(){}; ~classA(){}; }; struct structB { }; typedef std::set <classA*, structB> SETTYPE; typedef std::map <int, SETTYPE&g

在std::set invalidate迭代器中执行擦除调用吗?正如我在最后一行的第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 ?
        }
    }
}
A类
{
公众:
classA(){};
~classA(){};
};
结构
{
};
typedef std::set SETTYPE;
typedef std::map MAPTYPE;
内部cdecl wmain(内部argc,wchar\u t*参数[])
{
mapObj;
/*
...
…这里有些手术
...
*/
对于(MAPTYPE::迭代器itr1=mapObj.begin();itr1!=mapObj.end();itr1++)
{       
SETTYPE li=(*itr1).second;
对于(SETTYPE::迭代器itr2=li.begin();itr2!=li.end();itr2++)
{
类别A*lt=(类别A*)(*itr2);
li.擦除(itr2);
delete lt;//它是否使迭代器无效?
}
}
}

由于您显然只是在删除集合中的每个元素,因此您可以执行以下操作:

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

插入成员不得影响迭代器和对容器的引用的有效性,擦除成员应仅使迭代器和对已擦除元素的引用无效

编辑

在您的情况下,itr2在擦除后无效,因此递增它会导致未定义的行为。在这种情况下,您可以遵循reko_t的建议,一般来说,您可以尝试以下方法:

for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();) 
{
    classA *lt=(classA*)(*itr2);
    li.erase(itr2++); 
    delete lt;
}
它将在从集合中删除迭代器的上一个值之前递增迭代器。
顺便说一句,
delete lt不会使itr2失效,但通过
li.erase(itr2)

删除操作正常

问题是您擦除了itr2,从而使其无效,但将其用于循环迭代

i、 a.w.第一次擦除后,
++itr2
具有未定义的结果

我在这种情况下使用的模式是:

while(itr2 != end())
{
   iterator toDelete = itr2;
   ++itr2;   // increment before erasing!
   container.erase(toDelete);
}
一些非标准STL IMPL已将erase返回下一个迭代器,因此您可以执行以下操作:

while(itr2 != end())
   itr2 = container.erase();
但这不是便携式的



set
很奇怪,但是-在标准impl中,B将是比较器。

typedef std::set SETTYPE;我不知道为什么要将StructB作为std::set的第二个模板参数。std::set只保存一个值(与map一样,set没有键),第二个模板参数用于为集合提供比较函子(默认情况下std::less),因为这回答了我的Google“does set erase invalidate iterator”,这也是我最喜欢的回答我最喜欢的回答!