迭代器的有效性,擦除后()调用中的std ::集(iterator validity ,after

2019-09-01 22:30发布

不要抹去的std ::设为无效迭代器调用? 因为我有以下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 ?
        }
    }
}

Answer 1:

既然你是刚刚显然删除集的每一个元素,你可以只是做:

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


Answer 2:

从标准23.1.2

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

编辑

你的情况是itr2擦除所以递增它会导致不确定的行为无效。 在这种情况下,你可以按照reko_t建议,在一般情况下,你可以试试这个:

for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();) 
{
    classA *lt=(classA*)(*itr2);
    li.erase(itr2++); 
    delete lt;
}

这将删除它从组先前值之前,递增迭代器。
BTW。 itr2不被无效delete lt; ,但是通过li.erase(itr2);



Answer 3:

该删除就可以了。

问题是,你擦除-因而无效- itr2 ,但使用它的循环迭代。

IAW第一擦除之后, ++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将是比较器。



文章来源: iterator validity ,after erase() call in std::set
标签: c++ stl set