迭代器可能失效的情况
向容器中添加元素或者删除元素的操作都有可能导致容器元素的指针,引用和迭代器失效。失效的指针,引用和迭代器不能代表任何元素,所以要避免迭代器失效。
添加元素:
1.若容器是vector和string,且存储空间被重新分配,则会失效。若存储空间没有重新分配,指向插入位置之前的元素的指针,引用和迭代器仍然有效,但插入位置之后元素的指针,引用和迭代器会失效。
2.若容器是deque,插入到首位位置之外的任何位置都会导致指针,引用和迭代器失效,如果添加首位元素,迭代器会失效,指针,引用不会失效。
3.对于list和forward_list 指向容器的指针,引用和迭代器不会失效,需要特殊保存。(下有例子)
删除元素:
1.对于list和forward_list 指向容器其他位置的迭代器,指针,引用仍有效(下有例子)
2.对于deque,如果不是删除首位元素,则指针,引用和迭代器都会失效,若果删除的deque的尾元素,则位迭代器小,其他无影响,如删除首元素,则都不会受影响。
3.对于vector和string,指向删除元素之前的迭代器,指针,引用仍有效。
ps:当删除元素时,尾迭代器总是会失效。
list的插入删除处理迭代器
list<string> lst;
auto iter = lst.begin();
while(cin>>word)
{
iter = lst.insert(iter,word);//等价于调用push_front头插
}
因为iter初始化为首元素,insert插入操作会将读入的string插入到迭代器iter之前的位置,insert返回的迭代器iter改变为插入新元素的位置,所以可以之前重复插入读取单词。
//循环删除奇数位置
list<int> lst = {0,1,2,3,4,5,6,7};
auto it = lst.begin();
while(it!=lst.end())
{
if(*it%2)
it = lst.erase(it);//需要将it保存下来
else
++it;
}
erase删除指定位置元素后,返回下一个位置的迭代器,所以需特殊操作将其保存。
改变容器的循环程序
程序必须保证在循环内的每步操作都要更新迭代器,insert和erase操作都返回迭代器,可用作更新。
//删除偶数元素,复制每个奇数元素
vector<int> v = {0,1,2,3,4,5,6,7,8,9};
auto iter = v.begin();
while(iter != v.end())
{
if(*iter %2)
{iter = v.insert(iter,*iter);//复制奇数元素
iter+=2;//跳过复制的元素和原来的奇数,往后挪两个位置
}
else
{
iter = iter.erase(iter);//删除偶数元素并且指向下一个位置,
}
}
不要保存end返回的迭代器
如果在一个循环中,插入删除 deque,string, vector 中的元素,不要缓存end返回的迭代器,会失效。应该在每次循环判断时都重新计算end。