【C++】 vector 迭代器失效问题

news2024/10/1 5:47:42

【C++】 vector 迭代器失效问题

  • 一. 迭代器失效问题分析
  • 二. 对于vector可能会导致其迭代器失效的操作有:
      • 1. 会引起其底层空间改变的操作,都有可能是迭代器失效
      • 2. 指定位置元素的删除操作--erase
      • 3. Linux下,g++编译器对迭代器失效的检测并不是非常严格,处理也没有vs下极端。
      • 4. 与vector类似,string在 插入或 扩容操作 或 erase之后,迭代器也会失效

一. 迭代器失效问题分析

迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了封装,比如:vector的迭代器就是原生态指针T。因此迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器, 程序可能会崩溃)。

注意1:迭代器失效后,代码并不一定会崩溃,但是运行结果肯定不对,如果it不在begin和end范围内,肯定会崩溃的。

注意2:vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。 “ 其做法是,分配一个新的数组,然后将全部元素移到这个数组 ”。 但是原来定义的的迭代器未作处理依旧指向原来的地址,这就是导致迭代器失效的原因。
也就是说:一旦扩容就会导致迭代器失效。

迭代器失效解决办法:在使用前,对迭代器重新赋值即可

在这里插入图片描述
看图分析: 一旦经过扩容后原来的迭代器指针 it 不可在用,因为它还指向原来的旧空间,旧空间会被释放,旧空间释放后 it 就会变为野指针,需要重新更新迭代器即 newit

二. 对于vector可能会导致其迭代器失效的操作有:

1. 会引起其底层空间改变的操作,都有可能是迭代器失效

比如:resize、reserve、insert、assign、push_back等。

#include <iostream>
using namespace std;
#include <vector>
int main()
{
	vector<int> v{ 1,2,3,4,5,6 };

	auto it = v.begin();

	// 将有效元素个数增加到100个,多出的位置使用8填充,操作期间底层会扩容
	// v.resize(100, 8);

	// 插入元素期间,可能会引起扩容,而导致原空间被释放
	// v.insert(v.begin(), 0);
	// 
	// v.push_back(8);

	// 给vector重新赋值,可能会引起底层容量改变
	v.assign(100, 8);

	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
	return 0;
}

出错原因:以上操作,都有可能会导致vector扩容,也就是说vector底层原理旧空间被释放掉,而在打印时,it还使用的是释放之间的旧空间,在对it迭代器操作时,实际操作的是一块已经被释放的空间,而引起代码运行时崩溃。
解决方式:在以上操作完成之后,如果想要继续通过迭代器操作vector中的元素,只需给it重新赋值即可。

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

#include <iostream>
using namespace std;
#include <vector>
int main()
{
	int a[] = { 1, 2, 3, 4 };
	vector<int> v(a, a + sizeof(a) / sizeof(int));

	// 使用find查找3(第一个)所在位置的iterator
	vector<int>::iterator pos = find(v.begin(), v.end(), 3);

	// 删除pos位置的数据,导致pos迭代器失效。
	v.erase(pos);

	cout << *pos << endl; // 此处会导致非法访问
	return 0;
}

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

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

#include <iostream>
using namespace std;
#include <vector>
// 1. 扩容之后,迭代器已经失效了,程序虽然可以运行,但是运行结果已经不对了
int main()
{
	vector<int> v{ 1,2,3,4,5 };

	for (size_t i = 0; i < v.size(); ++i)
		cout << v[i] << " ";
	cout << endl;

	auto it = v.begin();
	cout << "扩容之前,vector的容量为: " << v.capacity() << endl;

	// 通过reserve将底层空间设置为100,目的是为了让vector的迭代器失效 
	v.reserve(100);
	cout << "扩容之后,vector的容量为: " << v.capacity() << endl;

	// 经过上述reserve之后,it迭代器肯定会失效,在vs下程序就直接崩溃了,但是linux下不会
	// 虽然可能运行,但是输出的结果是不对的

	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
	return 0;
}

4. 与vector类似,string在 插入或 扩容操作 或 erase之后,迭代器也会失效

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python从入门到高手3.5节-程序实战之最小值算法

目录 3.5.1 算法思路 3.5.2 构造随机数 3.5.3 条件控制语句 3.5.4 完整的代码实现 3.5.5 大神薯条老师 3.5.1 算法思路 算法原理很简单&#xff0c;先任取两个数进行比较&#xff0c;以计算两个数中的最小值&#xff1a; 假设得到的最小值为min_&#xff0c;再用这两个数…

PaddleDetection 自定义训练目标检测

PaddleDetection是一个基于PaddlePaddle的目标检测端到端开发套件&#xff0c;在提供丰富的模型组件和测试基准的同时&#xff0c;注重端到端的产业落地应用&#xff0c;通过打造产业级特色模型|工具、建设产业应用范例等手段&#xff0c;帮助开发者实现数据准备、模型选型、模…

制造企业各部门如何参与生产成本控制与管理?

​国内制造业的分量可不轻&#xff0c;从日常生活用品到高端工业设备&#xff0c;中国制造几乎涵盖了各个领域。 不过很多制造业企业在管理方面确实存在一些难题&#xff1a;成本控制不容易&#xff0c;产品质量并不稳定&#xff0c;生产周期也常常较长。 一、中国制造业生产管…

基于SpringBoot+Vue+MySQL的考勤管理系统

系统展示 管理员界面 用户界面 系统背景 随着企业规模的扩大和管理的精细化&#xff0c;传统的考勤方式已经无法满足现代企业的需求。纸质签到、人工统计不仅效率低下&#xff0c;还容易出错。因此&#xff0c;开发一套基于SpringBootVueMySQL的考勤管理系统显得尤为重要。该系…

基于微信小程序医院应急设备管理系统(源码+定制+解答)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

通过ChatGPT 提示词设定60种不同的写作风格

为 ChatGPT 编写正确的提示可以对您获得的响应类型产生很大影响。 您选择的写作风格会影响答案的语气、深度和清晰度。 本指南将帮助您发现 60 多种不同的写作风格,您可以与 ChatGPT 一起使用,以获得更多个性化 ChatGPT Prompt 中的写作风格是什么? ChatGPT 提示中的写作…

html空单元格的占位

先上代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title></head><body> <H1>我的WEB页面</H1><table border"2px" bgcolor"#7fffd4&…

Docker Compose 搭建 nacos 集群

主机准备 IProle192.168.142.155slave02192.168.142.156slave192.168.142.157master192.168.142.158slave03 在 slave03 上面准备 mysql services:mysql:image: mysql:8.0.31container_name: mysqlrestart: alwaysports:- 3306:3306volumes:- /data/nacos/nacos.sql:/data/n…

vue基于Spring Boot框架的高校实验室预约管理系统

目录 毕设制作流程功能和技术介绍系统实现截图开发核心技术介绍&#xff1a;使用说明开发步骤编译运行代码执行流程核心代码部分展示可行性分析软件测试详细视频演示源码获取 毕设制作流程 &#xff08;1&#xff09;与指导老师确定系统主要功能&#xff1b; &#xff08;2&am…

在java后端发送HTTPClient请求

简介 HttpClient遵循http协议的客户端编程工具包支持最新的http协议 部分依赖自动传递依赖了HttpClient的jar包 明明项目中没有引入 HttpClient 的Maven坐标&#xff0c;但是却可以直接使用HttpClient原因是&#xff1a;阿里云的sdk依赖中传递依赖了HttpClient的jar包 发送get请…

HTB:Archetype[WriteUP]

使用OpenVPN连接HTB服务器并启动靶机 靶机IP&#xff1a;10.129.95.187 分配IP&#xff1a;10.10.16.22 1.Which TCP port is hosting a database server? 使用nmap对靶机进行扫描&#xff1a;nmap -sC -sV -T4 -Pn {TARGET_IP} 通过nmap扫描结果可见&#xff1a; 1433 端口用…

C++ | Leetcode C++题解之第448题找到所有数组中消失的数字

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<int> findDisappearedNumbers(vector<int>& nums) {int n nums.size();for (auto& num : nums) {int x (num - 1) % n;nums[x] n;}vector<int> ret;for (int i 0; i < n;…

有效的字母异位词【字符串哈希】

题目 题解&#xff1a; 1.排序&#xff1a; #include<algorithm>class Solution{public:bool isAnagram(string s,string t){sort(s.begin(),s.end());sort(t.begin(),t.end());return st;} } 时间复杂度O(nlogn) 2.哈希表 #include<algorithm>int hash1[100]; …

旅游推荐|旅游推荐系统|基于Springboot+VUE的旅游推荐系统设计与实现(源码+数据库+文档)

旅游推荐系统 目录 基于java的旅游推荐系统设计与实现 一、前言 二、系统功能设计 三、系统实现 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布道师&#xf…

B端:常见通用模块有哪些,CRM除了通用模块,有哪些个性模块?

我经常把B端系统的功能模块分为通用模块和个性模块&#xff0c;通用模块是大部分系统都具备的功能&#xff0c;通用模块员工、日程、审批、代办等等&#xff0c;就是OA&#xff0c;通用模块生产、订单、物料、车间、设备、成本等等就是MES&#xff0c;这么说大家都晓得了吧&…

【pytorch】pytorch入门5:最大池化层(Pooling layers )

文章目录 前言一、定义概念 缩写二、参数三、最大池化操作四、使用步骤总结参考文献 前言 使用 B站小土堆课程 一、定义概念 缩写 池化&#xff08;Pooling&#xff09;是深度学习中常用的一种操作&#xff0c;用于降低卷积神经网络&#xff08;CNN&#xff09;或循环神经网…

Vue diff 算法介绍

首先我们来了解一下&#xff1a;diff 是什么&#xff1f; 通俗的讲&#xff0c;diff 就是比较两棵树&#xff0c;render 会生成两颗树&#xff0c;一棵新树 newVnode&#xff0c;一棵旧树 oldVnode&#xff0c;然后两棵树进行对比更新找差异就是 diff&#xff0c;全称 differe…

【cpp/c++ summary 工具】 Hunter 包管理器

Hunter 是一个跨平台cpp包管理器,点击查看支持的所有包的列表。 查看cmake是否满足 查看cmake是否满足Hunter版本要求&#xff1a; ubuntuDESKTOP-D7DRBER:~/CODE/mycpp/hunter-simple-master$ cmake --version cmake version 3.16.3CMake suite maintained and supported b…

88E1111使用技巧

一、88E1111简介 88E1111这款芯片是Marvel公司的产品&#xff0c;算是早期产品&#xff0c;但是市面上通用量较高&#xff0c;目前仍在大量使用&#xff0c;当然该公司也推出新产品&#xff0c;如88E1512&#xff0c;后续会有续篇&#xff0c;本篇文章重点讲述88E1111。 88E1…

66 使用注意力机制的seq2seq_by《李沐:动手学深度学习v2》pytorch版

系列文章目录 文章目录 系列文章目录动机加入注意力总结代码定义注意力解码器训练小结练习 我们来真的看一下实际应用中&#xff0c;key&#xff0c;value&#xff0c;query是什么东西&#xff0c;但是取决于应用场景不同&#xff0c;这三个东西会产生变化。先将放在seq2seq这个…