STL中容器vector迭代器失效的相关问题
迭代器失效,有两个层面的意思:
- 无法通过迭代器++,–操作遍历整个stl容器。记作: 第一层失效。
- 无法通过迭代器存取迭代器所指向的内存。 记作: 第二层失效。
vector是个连续内存存储的容器,如果vector容器的中间某个元素被删除或从中间插入一个元素, 有可能导致内存空间不够用而重新分配一块大的内存。 这个动作将导致先前获取的迭代器,,第一层和第二层均失效。 造成失效的两个函数:
● insert(i, value)
在迭代器i前插入一个元素value, 返回指向value迭代器
● erase(i)
删除迭代器i位置的元素, 返回指向后一个元素的迭代器
避免失效的方法:
● i = insert(i, value)
● i = erase(i)
造成失效的原因是因为内存的重新分配, 保留下来的迭代器不再指向容器中原来的元素…
下面我们来看一下执行这两个操作时内存分配的具体情况:
1. erase操作
//erase操作
#include<vector>
#include<iostream>
using namespace std;
int main(){vector<int>q{1,2,3,4,5,6,7,8,9,10};int cnt = 0;int flag = 0;for(vector<int>::iterator i = q.begin(); i != q.end(); ++i){++cnt;if(cnt > 15){cout<<"gg"<<endl;break;}if(*i == 3) //删除第三个i = q.erase(i);cout << *i << endl;cout << &(*i) << endl;}return 0;
}
output:
10xc7215820xc7215c40xc7216050xc7216460xc7216870xc7216c80xc7217090xc72174100xc72178
输出结果分析: 当删除第3个元素以后我们发现第四个元素是紧邻第二个元素的(刚好差一个int的内存)
也就是说vector执行erase(i)后会将迭代器i之后的元素逐个向前移动一个type单位
这也就是i及i之后所有迭代器失效的原因…
2. insert操作(内存不足时)
//insert操作
//内存不够情况
#include<vector>
#include<iostream>
using namespace std;
int main(){vector<int>q{1,2,3,4,5,6,7,8,9,10}; // c++11列表初始化vector<int>::iterator j = q.begin();j++;cout<<"第二个元素:"<<*j<<endl;cout<<"第二个元素地址:"<<&(*j)<<endl;cout<<"初始vector分配的容量:"<<q.capacity()<<endl; // 有多少元素即分配多少内存int cnt = 0;int flag = 0; //flag保证只插入一次for(vector<int>::iterator i = q.begin(); i != q.end(); ++i){++cnt;if(cnt > 15){cout<< "gg" <<endl;break;}if(*i == 3&&!flag){flag = 1;i = q.insert(i,22);cout<<"\n插入后第二个元素:"<<*j<<endl;cout<<"插入后第二个元素地址:"<<&(*j)<<endl;cout<<"插入元素后vector分配的容量:" <<q.capacity() <<endl;}cout << *i << endl;cout << &(*i) << endl;}return 0;
}
output:
第二个元素:2第二个元素地址:0xe5215c初始vector分配的容量:1010xe5215820xe5215c插入后第二个元素:15007936插入后第二个元素地址:0xe5215c插入元素后vector分配的容量:20220xe5219030xe5219440xe5219850xe5219c60xe521a070xe521a480xe521a890xe521ac100xe521b0
输出结果分析: vector内存分配策略为 二倍扩容 , 每次当内存不够的情况下vector会将容量扩展为当前的两倍.
那这些新分配的会在原内存的后面吗? 根据输出结果显然不是的。
上例代码在插入元素22 后, 新的3号元素内存位置距离上一个元素不是4byte(1个int单位), 也就是说
当vector扩容时, 会在另一个内存分配一段新的内存(原内存的二倍). 并把原内存中的元素全部拷贝到新内存中…
指向二号元素的迭代器在插入操作之后指向的值由2变成了15007936,也验证了上述结论.
3. insert操作(内存充足时)
//insert操作
//内存充足情况
#include<vector>
#include<iostream>
using namespace std;
int main(){vector<int>q{1,2,3,4,5,6,7,8,9,10}; q.push_back(11);cout<<"初始vector分配的容量:"<<q.capacity()<<endl; int cnt = 0;int flag = 0; //flag保证只插入一次for(vector<int>::iterator i = q.begin(); i != q.end(); ++i){++cnt;if(cnt > 15){cout<< "gg" <<endl;break;}if(*i == 3&&!flag){flag = 1;i = q.insert(i,22);cout<<"插入元素后vector分配的容量:" <<q.capacity() <<endl;}cout << *i << endl;cout << &(*i) << endl;}return 0;
}
output:
初始vector分配的容量:2010x1f218820x1f218c插入元素后vector分配的容量:20220x1f219030x1f219440x1f219850x1f219c60x1f21a070x1f21a480x1f21a890x1f21ac100x1f21b0110x1f21b4
输出结果分析:
很显然当内存充足的情况下, 执行insert操作只会将迭代器i及i之后的的所有元素向后移动一个type单位.所以这种情况下即使没有使用返回值也不会发生迭代器失效
STL中容器vector迭代器失效的相关问题相关推荐
- C++中STL和容器、迭代器、算法之间的关系
自学习C++以来,一直对STL.容器.迭代器.算法甚是困惑. 参考一些资料,加上自己的理解,整理如下 如果说程序等于数据结构+算法,STL就是一个小程序库,之所以说小,是因为容器模板中常用的函数有限, ...
- C++ STL : 模拟实现STL中的vector类
文章目录 vector vector的介绍 vector的优缺点 实现时需要注意的细节问题 1. Capacity增长问题 2. memset等函数来带的按字节拷贝问题 3. 深浅拷贝问题 4. 迭代 ...
- STL之容器Vector内存管理
大家都知道,STL中的vector容器的数据安排(线性空间或者叫块内存)及操作方式(支持随机访问),与array(数组)非常相似,唯一的差别在于前者为动态空间,随着元素的增加,内部机制会自动扩大空间而 ...
- 【C++】STL中 list 反向迭代器的模拟实现
在上篇文章实现了 list 后,我们实现了其对应的迭代器,但是对于 list,还有一个反向迭代器我们呢没有实现,但是反向迭代器不仅仅可以在 list 中使用,在 vector 中我们进行适配,同样也可 ...
- STL库容器vector at函数
STL库容器vector at函数 v.at(n)返回v指定位置n的元素.at函数比[]运算符更加安全, 因为它不会让你去访问到越界的元素,一旦越界将会在运行时中止程序并抛出一个异常std::out_ ...
- C++vector迭代器失效的问题
转载:http://blog.csdn.net/olanmomo/article/details/38420907 转载:http://blog.csdn.net/stpeace/article/de ...
- STL的erase()陷阱-迭代器失效总结
下面材料整理自Internet&著作. STL中的容器按存储方式分为两类,一类是按以数组形式存储的容器(如:vector .deque):另一类是以不连续的节点形式存储的容器(如:list.s ...
- STL源码剖析---迭代器失效小结
迭代器(iterator)是一个可以对其执行类似指针的操作(如:解除引用(operator*())和递增(operator++()))的对象,我们可以将它理解成为一个指针.但它又不是我们所谓普通的指针 ...
- C++STL中的vector
vector 容器 vector是C++标准模版库(STL,Standard Template Library)中的部分内容.之所以认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单的说: ...
最新文章
- c语言调式有错误,vsc调式c语言
- Java并发编程—线程间协作方式wait()、notify()、notifyAll()和Condition
- 为什么说Prometheus是足以取代Zabbix的监控神器?
- 来,看看你的单片机程序有多大!
- OC中的基本容器和基本数据类型
- 如何导出树结构清晰的代码机构目录
- EF ObjectStateManager 中已存在具有同一键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象...
- while 循环java_Java做while循环
- HttpServletRequest小结
- MySQL 新增、修改、删除 字段 sql语句
- FCM算法的matlab程序
- 未安装任何音频输出设备 解决方案
- html js css 简明教程,HTML+CSS+JavaScript网页制作简明教程
- [转载]你们要的GIF动图制作全攻略!看完就会做!(实操教程)
- 2.郝斌C语言课程大纲
- MySQL学习笔记整理(上部)
- untun 安装docker 随手记
- 撷半盏时光,叙岁月无恙。
- scada如何用oracle数据库,怎样设计SCADA系统数据库存储功能及其应用
- MLAPP(翻译)—第一章