总结常见的序列容器(vector、deque、list)和关联容器(set、multiset、map、multimap)的迭代器失效问题。

原迭代器指的是进行操作之前保存的迭代器,包括begin()、end()以及其他位置的迭代器。

vector:

成员函数push_back():会在容器末尾添加一个元素。如果容器有剩余空间(capacity() > size()),则直接添加新元素到容器尾部。此时,原迭代器中end()会失效,其他的都不会失效。否则,会导致容器重新分配内存,然后将数据从原内存复制到新内存,再在尾部添加新元素。此时,由于内存重新分配,原迭代器(所有)都失效。

成员函数pop_back():直接将容器中的最后一个元素删除,原迭代器中end()会失效,其余的都不会失效。

成员函数insert(iterator, n):如果容器有剩余空间,先在容器尾部插入一个元素,然后将插入点及之后的元素都向后移动一位,然后在插入点创建新元素。否则,会导致容器重新分配内存,接着将插入点之前的元素复制过去,在插入点创建新元素,再将插入点之后的元素复制过去。因此,如果没有内存的重新分配,原迭代器中插入点及插入点之后的迭代器(包括end())都失效。如果有内存的重新分配,原迭代器(所有)都失效。

成员函数erase(iterator):将删除点及之后的元素都向前移动一位,然后删除最后一个元素。因此,原迭代器中删除点之前的迭代器都有效,插入点及插入点之后的迭代器都失效。

deque:

成员函数push_back():会直接在容器末尾添加一个元素。原迭代器中end()会失效,其他的都不会失效。

成员函数push_front():会直接在容器头部添加一个元素。原迭代器中begin()会失效,其他的都不会失效。

成员函数pop_back():会直接删除最后一个元素。原迭代器中end()会失效,其他的都不会失效

成员函数pop_front():会直接在容器头部删除一个元素。原迭代器中begin()会失效,其他的都不会失效。

成员函数insert(iterator, n):如果插入点之前的元素较少,会在容器头部插入一个元素,然后将插入点及其之前的所有元素向前移动一位,再在插入点创建新元素。否则,将插入点及其之后的元素向后移动一位,再在插入点创建新元素。因此,向前移动则导致原迭代器中插入点及插入点之前的迭代器都失效;向后移动则导致迭代器中插入点及插入点之后的迭代器都失效。

成员函数erase(iterator):如果删除点之前的元素较少,将删除点之前的所有元素向后移动一位,再删除第一个元素。否则,将删除点之后的所有元素向前移动一位,再删除最后一个元素。因此,向前移动将导致原迭代器中删除点及删除点之后的迭代器失效;向后移动将导致原迭代器中删除点及删除点之前的迭代器都失效。

list:

因为list的底层结构是双向链表,所有操作都只是针对节点移动指针,不会涉及到位置变化,操作影响的范围很小。

成员函数push_back():原迭代器中end()会失效,其他的都不会失效。

成员函数push_front():原迭代器中begin()会失效,其他的都不会失效。

成员函数pop_back():原迭代器中end()会失效,其他的都不会失效

成员函数pop_front():原迭代器中begin()会失效,其他的都不会失效。

成员函数insert(iterator, n):原迭代器中插入点会失效,其他的都不会失效。

成员函数erase(iterator):原迭代器中删除点会失效,其他的都不会失效。

set、multiset、map、multimap

关联容器的底层结构为红黑树,所有操作同list一样,都只是移动指针,各成员函数导致的迭代器失效问题同list。

循环中删除元素

对于vector, erase会返回下一个iterator, 因此我们可以使用如下的方法:

#include <iostream>
#include <vector>using namespace std;int main()
{vector<int> a = {12, 23, 34, 45, 56, 67, 78, 89};auto iter = a.begin();while (iter != a.end()) {if (*iter > 30) {iter = a.erase(iter);}else {++iter;}}for (const auto &element : a) {cout<<element<<endl;}return 0;
}

输出:
12
23

对于map, 删除iterator只会影响当前的iterator, 因此使用for循环就够了, 比如:

#include <iostream>
#include <map>using namespace std;int main()
{map<int, int> a = {{1, 12}, {2, 23}, {3, 34}, {4, 45}, {5, 56}, {6, 67}};for (auto iter = a.begin(); iter != a.end(); ++iter) {if (iter->second > 30) {a.erase(iter);}}for (const auto &element : a) {cout<<element.first<<" : "<<element.second<<endl;}return 0;
}

输出:
1 : 12
2 : 23

更推荐的做法是在erase前让iterator指向下一个元素

#include <iostream>
#include <map>using namespace std;int main()
{map<int, int> a = {{1, 12}, {2, 23}, {3, 34}, {4, 45}, {5, 56}, {6, 67}};auto iter = a.begin();while (iter != a.end()) {if (iter->second > 30) {a.erase(iter++);}else {++iter;}}for (const auto &element : a) {cout<<element.first<<" : "<<element.second<<endl;}return 0;
}

输出:
1 : 12
2 : 23

STL 容器迭代器失效总结相关推荐

  1. STL——1、各类容器迭代器失效总结

    一. 种类: 标准STL序列容器:vector.string.deque和list. 标准STL关联容器:set.multiset.map和multimap. 非标准序列容器slist和rope:sl ...

  2. STL erase() 迭代器失效

    STL中的容器按存储方式分为两类:序列容器(如:vector .deque.list):关联容器(如:set.map) 两种容器在使用erase方法来删除元素时或产生迭代器失效的问题 对于非顺序序列容 ...

  3. c++ stl 容器 迭代器 stl用法示例

    1.基本概念 1.1容器概述 顺序容器 vector, deque,list 关联容器 set, multiset, map, multimap 容器适配器 stack, queue, priorit ...

  4. C++---STL中迭代器失效的总结

    我们在使用STL底层给我们提供的一些容器的时候,当我们给一个容器中增加(insert)或删除(erase),最有可能出现迭代器失效. 什么是迭代器失效 在对容器进行操作的时候,由于一些操作,使得元素保 ...

  5. STL容器迭代器的理解

    迭代器 迭代器模式:就是提供一种方式,不用暴露出容器内部结构,就可以通过迭代器来访问容器内部元素. 迭代器:迭代器是类模板,表现的像一个指针,一个可以对其执行类似于指针的操作(如:解引用operato ...

  6. C++(STL):09---vector迭代器失效问题

    在vector中,我们经常会使用迭代器iterator对vector中的元素进行索引,也经常需要将迭代器作为参数传递到vector的成员函数中,迭代器使用非常方便,但使用不当也会给我们带来巨大的麻烦, ...

  7. 容器删除元素后迭代器失效_STL 4: STL之容器:选择时机,删除元素,迭代器失效...

    一. 种类: 标准STL序列容器:vector.string.deque和list. 标准STL关联容器:set.multiset.map和multimap. 非标准序列容器slist和rope.sl ...

  8. STL源码剖析---STL容器特征总结(含迭代器失效)

    Vector 1.内部数据结构:连续存储,例如数组. 2.随机访问每个元素,所需要的时间为常量. 3.在末尾增加或删除元素所需时间与元素数目无关,在中间或开头增加或删除元素所需时间随元素数目呈线性变化 ...

  9. STL中容器vector迭代器失效的相关问题

    迭代器失效,有两个层面的意思: 无法通过迭代器++,–操作遍历整个stl容器.记作: 第一层失效. 无法通过迭代器存取迭代器所指向的内存. 记作: 第二层失效. vector是个连续内存存储的容器,如 ...

最新文章

  1. 重磅直播 | 图像对齐算法
  2. thinkphp5.0.9预处理导致的sql注入复现与详细分析
  3. Open/Close Port in Centos
  4. 魔兽巨龙追猎者服务器微信群,魔兽世界:难怪现在“龙脊”价格低,掉落率提升,群里一天出几个...
  5. anglar ajax执行2次的原因,AngularJS与Ajax表单提交需要单击两次
  6. .net 数据存储 mysql_asp.net实现存储和读取数据库图片
  7. 机器视觉:远心光学探秘
  8. Windows下Vim设置
  9. nginx处理域名后面多一个点
  10. window版本下载安装kafka和ZooKeeper并调试
  11. Ionicons的使用
  12. 如何用3天在成都逛吃玩过瘾?
  13. 计算机网络基础肖盛文电子书,网络实用教程
  14. 车架号VIN码精准查询车辆信息
  15. windows代码设置默认音频输出设备
  16. python勾股定理、0-30_求助python大神,显示Process finished with exit code 0.
  17. 浅谈SAP FICO—总账科目
  18. Currency Trading: Dollar in a Funk as Traders Bet on Slow Rebound
  19. Java 安全编程详解
  20. 【小狐狸 - 横版游戏开发】1.编辑素材 Til

热门文章

  1. ionic入门教程第十六课-在微信中使用ionic的解决方案(按需加载加强版)
  2. 2017帝都租房攻略:昌平通州租金涨幅高达25%
  3. javascript基础07
  4. apache 的工作模式
  5. 18 个 jQuery Mobile 开发贴士和教程
  6. [基础]Javascript中的继承示例代码
  7. 使用三目运算嵌套方法 或 临时变量方法: 获取三个整数中最大值的数
  8. App设计灵感之十二组精美的手机闹钟App设计案例
  9. uwsgi+python+flask+nginx服务器部署
  10. 2016年第七届蓝桥杯C/C++ C组国赛 —— 第二题:反幻方