C++:迭代器失效问题

目录

1.vector迭代器失效问题

1.底层空间改变

​编辑 2.指定位置元素的删除操作

2.Linux下的迭代器失效检测

1.扩容

2.删除

3.解决方法


1.vector迭代器失效问题

        迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了封装 ,比如: vector 的迭代器就是原生态指针 T* 。因此 迭代器失效,实际就是迭代器底层对应指针所指向的 空间被销毁了,而使用一块已经被释放的空间 ,造成的后果是程序崩溃 ( 如果继续使用已经失效的迭代器, 程序可能会崩溃 )
        在C++中,当一个vector进行了插入或删除操作时,其迭代器可能会失效。这是因为在插入或删除操作之后,vector可能会重新分配内存空间,导致原来的迭代器指向的位置不再有效。
可能会导致其迭代器失效的操作有

1.底层空间改变

1. 会引起其底层空间改变的操作,都有可能是迭代器失效 ,比如: resize reserve insert assign 、push_back等。
#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<vector>

int main()
{
	vector<int> v;
	v = { 1,2,3,4,5,6 };
	auto it = v.begin();
	//使用reserve扩容,可能会引起底层容量的改变,旧空间释放,但是it依旧使用的时释放前的旧空间
	v.reserve(100);
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}

	return 0;
}
我们使用resize reserve insert assign、 push_back等操作都可能会导致扩容, 也就是说vector底层原理旧空间被释放掉, 而在打印时,it还使用的是释放之间的旧空间,在对it迭代器操作时,实际操作的是一块已经被释放的 空间,而引起代码运行时崩溃。
如果我们在扩容后重新赋值即可解决这个问题,可以继续操作it迭代器。

 2.指定位置元素的删除操作

#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<vector>

int main()
{
	vector<int> v;
	v = { 1,2,3,4,5,6 };
	//auto it = v.begin();
	//使用reserve扩容,可能会引起底层容量的改变,旧空间释放,但是it依旧使用的时释放前的旧空间
	//v.reserve(100);
	auto it = v.begin();
	while (it != v.end())
	{
		v.erase(it);  //删除it位置的数据,导致迭代器失效
		//这时再对it进行操作就是非法访问
		cout << *it << endl;
		++it;
	}

	return 0;
}

如图中代码,运行会崩溃

erase 删除 pos 位置元素后, pos 位置之后的元素会往前搬移,没有导致底层空间的改变,理论上讲迭代器不应该会失效,但是:如果pos 刚好是最后一个元素,删完之后 pos 刚好是 end 的位置,而 end 位置是没有元素的,那么pos 就失效了。因此删除 vector 中任意位置上元素时, vs 就认为该位置迭代器失效了。

如果在删除后对迭代器it重新赋值,这个时候就不会失效,因为erase返回删除元素下一个位置元素的迭代器。

2.Linux下的迭代器失效检测

Linux 下, g++ 编译器对迭代器失效的检测并不是非常严格,处理也没有 vs 下极端。

1.扩容

运行如下代码:

 

可以运行但是结果已经出错。

2.删除

运行如下代码

可以正常运行,erase删除任意位置代码后,linux下迭代器并没有失效 因为空间还是原来的空间,后序元素往前搬移了,it的位置还是有效的

但是如果删除的是最后一个元素呢

程序崩溃,因为删除最后一个元素,删除后it已经超过end,++it导致程序崩溃

3.解决方法

vector 类似, string 在插入 + 扩容操作 +erase 之后,迭代器也会失效
迭代器失效解决办法:在使用前,对迭代器重新赋值即可

1.在进行插入或删除操作之后,更新迭代器的位置,使其指向有效的元素。

2.在进行插入或删除操作之前,先将迭代器保存下来,然后再进行操作之后重新定位迭代器。

3.另外,C++11引入了emplace_back()和emplace()函数,它们可以在vector中直接构造对象,而不是先创建临时对象再插入,这样可以减少迭代器失效的可能性 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/344854.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

uniapp设置隐藏原生导航栏(3)

1、单个页面隐藏 在pages.json里配置 (第一种方式) {"path": "pages/home/index","style": {"navigationBarTitleText": "首页","navigationStyle": "custom" // 使用自定义导航栏&#xff0c;系统会关…

LoadRunner从零开始之走近LoadRunner

3.1 LoadRunner 的运行原理 安装LoadRunner 后&#xff0c;在菜单“开始” 一“MercuryLoadRunner” 中&#xff0c;你会看 到这样一组程序&#xff0c;如图 3-1 所示。 • 其中Applications 下面的Analysis、Controller 和Virtual User Generator 是我们 做性能测试最常用的…

【基础配置】Python2/Python3并存安装配置教程

Nx01 产品简介 Python是一种高级的、解释型的、面向对象的通用编程语言&#xff0c;具有简单易学、代码可读性强、功能强大、可移植性好等特点。它可以应用于多种领域&#xff0c;如Web开发、数据科学、人工智能、机器学习、科学计算、自动化测试等。Python由Guido van Rossum于…

08章【文件与IO】

文章目录 File类IO流字节流字符流字节字符转换流缓冲流打印流对象流字节数组流数据流字符串流、管道流、合并流 RandomAccessFileProperties文件操作文件压缩与解压缩装饰者模式常见字符编码New IO File类 File类的基本概念 File类&#xff1a;表示文件和目录路径名的抽象表示…

【AIGC】CLIP

CLIP的基本原理 对比学习&#xff1a; Clip使用对比学习来训练模型。对比学习的目标是通过将正样本&#xff08;相似的图像和文本对&#xff09;与负样本&#xff08;不相似的图像和文本对&#xff09;进行比较&#xff0c;从而使模型学会区分不同样本之间的差异。这有助于模型…

仰暮计划|“每个人三发子弹,我打中两靶子,还有一发子弹让我打到红薯地里了”

“百善孝为先”&#xff0c;爱老、敬老一直是我们的优秀传统文化&#xff0c;一直是流淌在我们体内的文化基因。中国历朝历代有着丰富的养老文化&#xff0c;还有一系列的爱老敬老政策。无论是从周代创建的养老礼制度&#xff0c;还是春秋时期开始的古代养老文化&#xff0c;亦…

C#使用IsLeapYear方法判断指定年份是否为闰年

目录 一、判断指定年是否为闰年的2个方法 1.使用IsLeapYear方法判断指定年份是否为闰年 2.使用自定义的算法计算指定年份是否为闰年 二、示例 1.方法1的实例 2.方法2的实例 一、判断指定年是否为闰年的2个方法 1.使用IsLeapYear方法判断指定年份是否为闰年 使用IsLeapY…

C语言进阶——数据结构之链表(续)

前言 hello&#xff0c;大家好呀&#xff0c;我是Humble&#xff0c;本篇博客承接之前的C语言进阶——数据结构之链表 的内容&#xff08;没看过的小伙伴可以从我创建的专栏C语言进阶之数据结构 找到那篇文章并阅读后在回来哦~&#xff09;&#xff0c;上次我们重点说了链表中…

2023年智能可穿戴行业市场分析(电商数据查询分析):智能手表销额增长21%,手环明显下滑

近年来&#xff0c;随着技术的进步&#xff0c;智能可穿戴设备在社交网络、医疗保健、导航等诸多领域有着非常广泛的应用&#xff0c;这为大众生活带来了诸多便利。 当前的可穿戴产品形态纷繁多样&#xff0c;主要包括智能手表、智能眼镜、智能手环、健康穿戴和体感控制等等&am…

Java框架篇面试题

&#x1f4d5;作者简介&#xff1a; 过去日记&#xff0c;致力于Java、GoLang,Rust等多种编程语言&#xff0c;热爱技术&#xff0c;喜欢游戏的博主。 &#x1f4d7;本文收录于java面试题系列&#xff0c;大家有兴趣的可以看一看 &#x1f4d8;相关专栏Rust初阶教程、go语言基…

【江科大】STM32:I2C通信外设(硬件)

在将2C通信外设之前&#xff0c;我们先捋一捋&#xff0c;串口的相关特点来和2C进行一个对北比。 首先&#xff1a; 1,大部分单片机&#xff0c;设计的PCB板均带有串口通信的引脚&#xff08;也就是通信基本都借助硬件收发器来实现&#xff09; 2.对于串口的异步时序&#xff0…

什么样的宣传才能对消费者起效?

品牌离不开宣传&#xff0c;宣传又直接面向消费者&#xff0c;然后面对铺天盖地的宣传&#xff0c;除了从业人员&#xff0c;相信大部分用户都会有抵触心理&#xff0c;今天媒介盒子就来和大家聊聊&#xff0c;什么样的宣传能够提高消费者的接受度&#xff0c;让宣传不白宣传。…

elementui 表单 resetFields 方法不生效问题解决

问题 调用 elementui 官方提供的表单重置方法 resetFields 方法重置表单不生效&#xff0c;相信很多小伙伴都遇到过这个问题。 解决方法 检查代码看每个表单项的 prop 与 v-model 绑定的属性值命名是否相同&#xff0c;不相同的话就会导致 resetFields 方法不生效的问题&am…

AI技术的崛起:软件工程师的新篇章

随着人工智能&#xff08;AI&#xff09;技术的迅猛发展与普及&#xff0c;各行各业都受到了前所未有的冲击与变革。 对于软件工程师而言&#xff0c;AI技术的崛起既带来了挑战&#xff0c;也带来了前所未有的机遇。本文将探讨AI技术对软件工程师的影响&#xff0c;以及如何应…

vue2面试题:什么是双向数据绑定

vue2面试题&#xff1a;什么是双向数据绑定 回答思路&#xff1a;1.什么是双向绑定-->2.双向数据绑定的原理-->3.如何实现双向数据绑定1.什么是双向绑定2.双向数据绑定的原理3.如何实现双向数据绑定来一个构造函数&#xff1a;执行初始化&#xff0c;对data执行响应化处理…

Linux: make/Makefile 相关的知识

背景&#xff1a; 会不会写makefile&#xff0c;从一个侧面说明了一个人是否具备完成大型工程的能力一个工程中的源文件不计数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;makefile定义了一系列的 规则来指定&#xff0c;哪些文件需要先编译&#xff0c…

ubuntu22.04安装filebeat报错解决

1、查看报错 journalctl -u filebeat 或者 filebeat -c /etc/filebeat/filebeat.yml找到报错信息 runtime/cgo: pthread_create failed: Operation not permitted 2、解决报错 在filebeat.yml配置文件添加如下配置&#xff0c;重启filebeat seccomp:default_action: allow…

ansible 常用模块

目录 1.ping模块 2.command模块 3. shell模块 4.copy模块 5.file模块 6.fetch模块 7.cron模块 8.yum模块 9.service模块 10.user模块 11.group模块 12.script 模块 13.setup模块 14. get_url模块 15.stat模块 16.unarchive模块 1.ping模块 使用ansible db1 -m pin…

【数学建模】综合评价方法

文章目录 综合评价的基本理论和数据预处理综合评价的基本概念综合评价体系的构建综合指标的预处理方法评价指标预处理示例 常用的综合评价数学模型线性加权综合评价模型TOPSIS法灰色关联度分析熵值法秩和比&#xff08;RSR&#xff09;法综合评价示例 综合评价的基本理论和数据…

NODE笔记 2 使用node操作飞书多维表格

前面简单介绍了node与简单的应用&#xff0c;本文通过结合飞书官方文档 使用node对飞书多维表格进行简单的操作&#xff08;获取token 查询多维表格recordid&#xff0c;删除多行数据&#xff0c;新增数据&#xff09; 文章目录 前言 前两篇文章对node做了简单的介绍&#xff…