前言

迭代器(iterator)是一个对其执行类似指针操作的对象,我们平常理解它为一个指针,但它其实并不是我们所谓真正意义上的指针,当你sizeof查看时,会发现其所占内存并不是4字节。

迭代器是个所谓的复杂的指针,具有遍历复杂数据结构的能力。其下层运行机制取决于其所遍历的数据结构。因此,每一种容器型都必须提供自己的迭代器。

那么,大致介绍完迭代器的概念,下面来探讨下迭代器在各种容器中失效的情况,其可分为两种类型:

序列式容器迭代器失效

关联式容器迭代器失效

序列式容器迭代器失效

概述

所谓序列容器,即以线性排列(类似普通数组的存储方式)来存储某一指定类型(例如 int、double 等)的数据,例如vector、deque...等。

失效原因

当程序员对当前的元素迭代器iterator进行删除操作时,其后的所有元素的迭代器都会失效,这是因为序列式容器都是连续分配的内存空间,当对其进行erase操作时,后面的所有元素都会向前移动。【解决思路:erase返回下一个有效的iterator】

代码实现

/*-----失效代码-----*/
void vectorTest()
{
vector container;
vector::iterator iter;
for (iter = container.begin(); iter != container.end(); iter++)
{
if (*iter > 3)
container.erase(iter); // iter自增,但iter已失效
}
for (iter = container.begin(); iter != container.end(); iter++)
{
cout<
}
}
/*-----有效代码-----*/
for (iter = cont.begin(); iter != cont.end();)
{
(*it)->doSomething();
if (shouldDelete(*iter))
iter = cont.erase(iter); //erase删除元素,返回下一个迭代器
else
++iter;
}

关联式容器迭代器失效

概述

所谓关联式容器,其实就是在存储元素值的同时,还会为各元素额外再配备一个值(又称为“键”,即key),它的功能是在使用关联式容器的过程中,如果已知目标元素的键的值,则直接通过该键就可以找到目标元素,而无需再通过遍历整个容器的方式。【需要注意的是,序列式容器的元素默认是未经过排序的,而关联式容器默认是通过键值大小进行升序排序】

失效原因

对于关联容器(如map, set,multimap,multiset),删除当前的iterator,仅仅会使当前的iterator失效,只要在erase时,递增当前iterator即可。这是因为map之类的容器,使用了红黑树来实现,插入、删除一个结点不会对其他结点造成影响。erase迭代器只是被删元素的迭代器失效,但是返回值为void,所以要采用erase(iter++)自增方式删除迭代器。

代码实现

/*-----失效代码-----*/
void mapTest()
{
mapm;
for (int i = 0; i < 10; i++)
{
m.insert(make_pair(i, i + 1));
}
map::iterator it;
for (it = m.begin(); it != m.end(); it++)
{
if ((it->first)>5)
m.erase(it); // 此处迭代器失效,并it不能++
}
}
/*-----有效代码-----*/
for (it = m.begin(); it != m.end(); it++)
{
if (it->first==5)
m.erase(it++);
实际步骤:
it加入erase ;
然后it自增 ; // 这里it已经失效,通过++跳到下一个迭代器
然后erase执行。
}