迭代器失效有两个层面的意思
- 无法通过迭代器++,–操作遍历整个stl容器。记作: 第一层失效。
- 无法通过迭代器存取迭代器所指向的内存。 记作: 第二层失效。
造成失效的两个函数
- insert(i, value)
在迭代器i前插入一个元素value, 返回指向value迭代器- erase(i)
删除迭代器i位置的元素, 返回指向后一个元素的迭代器
避免失效的方法
- i = insert(i, value)
- i = erase(i)
对于迭代器失效,可以分为数组型、链表型、树型结构几种结构来说。
数组型
对于vector、deque等连续存储的容器来说,插入元素(insert)或者删除元素(erase),会导致后边的迭代器都失效,解决方法是,erase(*iter)会返回下一个有效迭代器的值,删除元素时用将当前迭代器赋值为erase的返回值,系统会自动将迭代器的指向修改的。
for (iter = cont.begin(); iter != cont.end();)
{
(*it)->doSomething();
if (shouldDelete(*iter))
iter = cont.erase(iter); //erase删除元素,返回下一个迭代器
else
++iter;
}
迭代器失效
void vectorTest()
{
vector<int> container;
for (int i = 0; i < 10; i++)
{
container.push_back(i);
}
vector<int>::iterator iter;
for (iter = container.begin(); iter != container.end(); iter++)
{
if (*iter > 3)
container.erase(iter);
}
for (iter = container.begin(); iter != container.end(); iter++)
{
cout<<*iter<<endl;
}
}
报错是:vectoriterator not incrementable.
但是erase方法可以返回下一个有效的iterator。所以代码做如下修改,就OK了。
void vectorTest()
{
vector<int> container;
for (int i = 0; i < 10; i++)
{
container.push_back(i);
}
vector<int>::iterator iter;
for (iter = container.begin(); iter != container.end(); iter++)
{
if (*iter > 3)
iter = container.erase(iter);
else
iter++;
}
for (iter = container.begin(); iter != container.end(); iter++)
{
cout<<*iter<<endl;
}
链表型
对于list型的数据结构,使用了不连续分配的内存,删除运算使指向删除位置的迭代器失效,但是不会失效其他迭代器.解决办法两种,erase(*iter)会返回下一个有效迭代器的值,或者erase(iter++).
树型结构
对于map,set,multimap,multiset来说, 使用红黑树来存储数据,插入不会使得任何迭代器失效;删除运算使指向删除位置的迭代器失效,但是不会失效其他迭代器.erase迭代器只是被删元素的迭代器失效,但是返回值为void,所以要采用erase(iter++)的方式删除迭代器.