写点什么

迭代器失效问题

作者:Maybe_fl
  • 2022-11-16
    陕西
  • 本文字数:1205 字

    阅读完需:约 4 分钟

容器的遍历在我们的代码中是经常出现的场景

for(auto iter = T.begin(); iter != T.end(); ++iter){  ...}
复制代码

在业务逻辑中,难免出现容器的增删改查这些操作,静态操作(改、查)由于不设涉及容器结构的变化,只是数据的变化,不会出现迭代器失效问题。只有动态操作(增、删),但增的操作一般不会持续整个遍历期间,重点介绍删操作。


erase


map

首先看一下 erase()函数原型。分为两种情况

C++98

(1)	void erase (iterator position);(2)	size_type erase (const key_type& k);(3)	void erase (iterator first, iterator last);
复制代码

C++11

(1)	iterator  erase (const_iterator position);(2)	size_type erase (const key_type& k);(3)	iterator  erase (const_iterator first, const_iterator last);
复制代码

map 执行 erase()操作后,删除的迭代器会失效,其他迭代器仍不失效。

错误写法

for(auto iter = map.begin(); iter != map.end(); ++iter){  if(...)  {    ...    iter = map.erase(iter);  }}
复制代码

由于代码执行 map.erase(iter)操作后,iter 已经不在红黑树里面了,执行++iter 操作无法找到它的直接后继,代码会出错。

正确写法:

for(map<T>::iterator iter = map.begin(); iter != map.end(); ){  if(...)  {    map.erase(iter++);   //C++11,C++98都支持    //iter = map.erase(iter);   仅仅支持C++11,C++98不支持  }  else  {    ++iter;  }}
复制代码

在不确定编译器是否支持 C++11 的情况下,上述写法更安全。


list

erase()函数原型

C++98

iterator erase (iterator position);iterator erase (iterator first, iterator last);
复制代码

C++11

iterator erase (const_iterator position);iterator erase (const_iterator first, const_iterator last);
复制代码

list 执行 erase()操作后,删除的迭代器会失效,其他迭代器仍不失效。

可以发现函数返回值与 map 还是有所差异的

for(list<T>::iterator iter = list.begin(); iter != list.end(); ){  if(...)  {    list.erase(iter++);   //C++11,C++98都支持    //iter = list.erase(iter);   //C++11,C++98都支持  }  else  {    ++iter;  }}
复制代码

上述两种写法 C++11、C++98 都是支持的


vector

C++98

iterator erase (iterator position);iterator erase (iterator first, iterator last);
复制代码

C++11

iterator erase (const_iterator position);iterator erase (const_iterator first, const_iterator last);
复制代码

vector 虽然提供了 erase 操作,但是并不建议使用,erase 操作后,position 之前的迭代器不会失效,position 之后的迭代器会失效。


insert

map 和 list 的 insert 操作不会导致其他迭代器的失效,但 vector 就不一样,会导致迭代器失效,因为 insert 会产生扩容操作,扩容操作之后,所有的迭代器都会失效。vector 的 insert 接口不建议调用,本身使用概率低,但更多的应该注意 vector.push_back()操作,因为此操作同样有可能会触发扩容操作,导致之前记录的所有迭代器全部失效,需要重点关注。

用户头像

Maybe_fl

关注

还未添加个人签名 2019-11-11 加入

还未添加个人简介

评论

发布
暂无评论
迭代器失效问题_Maybe_fl_InfoQ写作社区