c++: 迭代器失效

发布时间 2023-12-15 21:50:58作者: Freedom_lyx

一、序列式容器

序列式容器(如 vector, deque)的迭代器删除正确的做法如下:

 1 // 在这里想把等于2的元素都删除
 2 for(auto it=q.begin();it!=q.end();)
 3 {
 4     if(*it==2)
 5     {
 6         it=q.erase(it); // 这里会返回指向下一个元素的迭代器,因此不需要再自加了
 7     }
 8     else
 9     {
10         it++;
11     }
12 }

 

二、链表式容器

对于链表式容器(如 list),删除当前的 iterator,仅仅会使当前的 iterator 失效,这是因为 list 之类的容器,使用了链表来实现,插入、删除一个结点不会对其他结点造成影响。只要在 erase 时,递增当前 iterator 即可,并且 erase 方法可以返回下一个有效的 iterator。

方式一:递增当前 iterator

1 for (iter = cont.begin(); it != cont.end();)
2 {
3    (*iter)->doSomething();
4    if (shouldDelete(*iter))
5       cont.erase(iter++);
6    else
7       iter++;
8 }

方式二:通过 erase 获得下一个有效的 iterator

1 for (iter = cont.begin(); iter != cont.end();)
2 {
3    (*it)->doSomething();
4    if (shouldDelete(*iter))
5       iter = cont.erase(iter);  //erase删除元素,返回下一个迭代器
6    else
7       ++iter;
8 }

三、关联式容器

例如map、set;
删除当前的iterator,仅仅会使当前的iterator失效,只要在erase失效,只要在erase时递增当前iterator即可。这是因为map之类的容器,使用了红黑树来实现,插入、删除一个结点不会对其他结点造成影响。erase迭代器只是被删除元素的迭代器先来看一下map迭代器失效的一个例子。

问题:

for (it = m.begin(); it != m.end(); it++)
{
    if ((it->first)>5)
        m.erase(it);
}

解决问题:

方法一:

for (it = m.begin(); it != m.end(); )
{
    if (it->first==5)
        m.erase(it++);//先把iter传值到erase里面,然后iter自增,然后执行erase,所以iter在失效前已经自增了
    it++;
}

方法二:

for (it = m.begin(); it != m.end(); )
{
    if (it->first==5)
    {
      it = m.erase(it);//获得有效的迭代器
    }
    else
    {
    ++it; } }