当前位置:网站首页>迭代器失效问题
迭代器失效问题
2022-08-02 09:26:00 【*insist】
vector容器是一个顺序容器 类似于线性表 空间是连续的 而且其接口大多都是和迭代器关联起来的 但是它会存在一个迭代器失效的问题
- 迭代器失效问题分为两类:
1.经过某些操作后迭代器的意义发生改变
2.迭代器指向的空间被释放后或者空间扩容后该迭代器就会失效(不可再使用)
第一类
例一:
vector成员函数insert()涉及的迭代器失效问题
void teststdvector()
{
vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(4);
v.push_back(9);
v.push_back(10);
v.push_back(12);
for (auto& e : v)
{
cout << e << endl;
}
vector<int>::iterator it = v.begin();
auto pos = find(v.begin(), v.end(), 3);
if(pos!=v.end())
cout<<endl;
v.insert(pos, 88);
cout<<*pos<<endl;
}
在vector容器中尾插数据,然后在用算法库里的find函数在v的迭代器区间内找指向3的迭代器,再调用insert函数 在3的位置插入一个88 之后在对该迭代器进行解引用访问(vector的迭代器是原生指针T*,所以可以解引用),这个时候就会出现迭代器失效了,因为插入数据后原先3位置的迭代器就会发生改变,3的位置插入了新的数据,那么原先3的迭代器就会指向新插入的数据,迭代器的意义发生了变化,这就是第一种迭代器失效问题!
对于迭代器失效的检查,vs下的pj版编译器 和 linux下的gcc编译器检查力度不同,vs下检查很严格,不允许访问失效的迭代器 linux 下基本不检查!
下面是两个平台下上段代码的运行结果:
vs 2019下打印完插入的数据后就运行崩溃了!vs 2013 的版本会直接断言报错。
linux下即使是失效的迭代器,仍然可以访问,程序正常运行通过,编译器不做检查。
同样vector的成员函数erase()也涉及迭代器失效问题:
void teststdvector3()
{
vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(4);
v.push_back(9);
v.push_back(10);
v.push_back(12);
auto pos = find(v.begin(), v.end(), 3);
if (pos != v.end())
{
v.erase(pos);
}
cout << *pos << endl;
}
erase的返回值是删除元素位置的下一个位置的迭代器 也就还是pos(我们传的迭代器),此时的pos的意义已经发生了改变,由原先元素的迭代器变成了其一个元素的迭代器,已经失效了,不能再通过该迭代器访问原先的元素!!!
例二
用erase删除vector中所有偶数的方法
下面先举例错误的方法:
//错误的代码
void testerase1()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
auto it = v.begin();
while (it != v.end())
{
//正常的思路就是 如果迭代器一直往后走 迭代器指向元素是偶数 就删除
if (*it % 2 == 0)
{
v.erase(it);
}
++it;
}
for (auto& e : v)
{
cout << e << endl;
}
}
上述代码的运行图解:
这种方法就会漏掉数据,相邻的偶数或者一奇一偶就会·漏掉元素
正确的使用方法:
要防止代码中的it迭代器盲目往后走 需要判断如果是删除了那么就让it等于当前位置的下一个位置 否则就往后走也就是如果删除就让it接收erase的返回值,因为其返回值就是删除元素的一个元素的迭代器!
只需要改动一下代码即可
void testerase4()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
auto it = v.begin();
while (it != v.end())
{
//用if else控制 进行了删除操作就让it接收erase的返回值
//那么it就会变成已经删除元素的下一个元素的迭代器 符合逻辑
//如果没有进行删除 说明是奇数 就让it往后++ 跳过奇数即可
if (*it % 2 == 0)
{
it = v.erase(it);
}
else
{
++it;
}
}
for (auto& e : v)
{
cout << e << endl;
}
}
更改后的代码正常运行,如下:
第二类
迭代器指向的空间已经被释放掉,再次使用该迭代器访问其原先指向的元素,就也会报错,因为该迭代器空间释放后就已经失效了,不可以再使用(就是野指针,vector的迭代器就是原生指针的封装)!!!
第二种迭代器失效就是要注意扩容后原先的迭代器是属于原来空间的,原空间被释放后其不能再直接使用,需要更新至新空间的位置上,才可以使用,否则就是失效的迭代器!!!
边栏推荐
- 理解JS的三座大山
- Talk about the understanding of Volatile
- 单机部署flink,创建oracle19c rac的连接表时报错 ORA-12505 ,怎么回事?
- spark:页面单跳转换率统计(案例)
- tf中tensor的大小输出
- Using the TCP protocol, will there be no packet loss?
- Re22:读论文 HetSANN An Attention-based Graph Neural Network for Heterogeneous Structural Learning
- nacos项目搭建
- AutoJs学习-密码生成器
- 李航《统计学习方法》笔记之朴素贝叶斯法
猜你喜欢
随机推荐
单词接龙 II
Jenkins--基础--07--Blue Ocean
sql concat(),如何才能拼接表的名字
线程池的使用及ThreadPoolExecutor源码分析
Pytorch's LSTM parameters explained
Jetpack Compose 中的状态管理
typeinfo类型支持库学习
自定义View实现波浪荡漾效果
YugaByte adds Voyager migration service in its 2.15 database update
不用Swagger,那我用啥?
中国发布丨滴滴因违反网络安全法等被罚80.26亿元!调查细节公布
tf中tensor的大小输出
要长续航还是更安全?海豹与深蓝SL03对比导购
net start mysql MySQL 服务正在启动 . MySQL 服务无法启动。 服务没有报告任何错误。
Jenkins--基础--5.4--系统配置--全局工具配置
ABAP 和json转换的方法
XML简介
Overview of Edge Computing Open Source Projects
leetcode:81. 搜索旋转排序数组 II
动态规划每日一练(3)