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

news2024/9/22 21:17:09

本文是对vector迭代器失效问题的分析,需要对vector有一定了解,若还不了解的可以看这篇文章进行学习:【C++】容器vector常用接口详解-CSDN博客


目录

一.什么是迭代器失效?

二.迭代器失效的典型案例

1.引起底层空间改变

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

三. Linux环境下g++对迭代器失效的检测


一.什么是迭代器失效?

先来看一段代码:

//构造一个1,2,3,4构成的vector
vector<int> v;
for (size_t i = 1; i < 5; i++)
{
	v.push_back(i);
}

//找到其中3这个值的位置
auto pos = find(v.begin(), v.end(), 3);
v.insert(pos, 30);
v.insert(pos, 40);

这就是一个典型的迭代器失效问题,要弄清楚为什么,首先我们需要清楚一点:vector的每一次扩容都不是在原地扩容,而是新开辟一块空间后将原先的数据拷贝到新空间 

而这就产生了一个问题,第一次insert的pos是表示3的位置,但第二次insert时pos还是表示3的位置吗?如下图所示:

因此可以得到一个结论:迭代器失效,本质就是迭代器底层对应指针所指向的空间被销毁了,使用了一块已经被释放的空间,造成的后果是程序崩溃。 

二.迭代器失效的典型案例

1.引起底层空间改变

理解了迭代器失效的原理后,直到只要是引起底层空间改变的操作,都有可能使得迭代器失效,例如常规的:resize、reserve、insert、assign、push_back等

vector<int> v{ 1,2,3,4,5,6 };
auto it = v.begin();

//将有效元素增加到20个,多余的用0填充,操作期间底层扩容
v.resize(20, 0);
//改变容量大小为20,可能会进行扩容而引起底层改变
v.reserve(20);

//插入元素,可能会进行扩容
v.push_back(8);
v.insert(v.begin(), 0);

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

//以上操作都会导致先前的迭代器it失效
//解决方法就是完成上述操作后更新迭代器it
//若在此不更新就会出错
it = v.begin();
while (it != v.end())
{
	cout << *it << " ";
	it++;
}
cout << endl;

无论是上面的哪一行代码(resize,reserve,push_back等等),只有进行了 扩容操作 都会改变底层空间,使得原迭代器it指向的是原位置的失效空间 

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

vector<int> v{ 1,2,3,4 };
auto pos = find(v.begin(), v.end(), 3);//找到3的位置
v.erase(pos);//删除3
cout << *pos << endl;//再次解引用就会报错

erase删除pos位置元素后,pos位置之后的元素都会往前移动,虽然说没有导致底层空间的改变,理论上说迭代器应该不会失效,但是若pos恰好是最后一个元素的位置,删除完后迭代器是end的位置了呢,此时pos就不指向任何元素,也就失效了,为了防止这种情况,vs下就认为删除vector中任意位置上元素后,该位置的迭代器就已经失效了。 

举个例子:若要删除vector中所有的偶数

vector<int> v{ 1, 2, 3, 4, 5, 6, 7, 8 };
auto it = v.begin();
while (it != v.end())
{
	if (*it % 2 == 0)
	{
		//erase返回的是删除位置的下一个元素的位置的迭代器
		//这里就直接利用erase的返回值进行更新
		it = v.erase(it);
	}
	else
	{
		it++;
	}
}
for (auto e : v)
{
	cout << e << " ";
}
cout << endl;

三. Linux环境下g++对迭代器失效的检测

在Linux环境下,g++对迭代器失效的检测没有vs上那么严格,例如以下代码是可以在g++下运行的,但是由于迭代器失效的原因,这段代码打印出来一定是错误的

int main()
{
	std::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;
}

Linux和Windows环境下,对于erase更加不一样。Linux下,因为erase没有空间的扩容,因此原来的空间依然是原来空间,只要不是删除最后一个元素就不会有问题,而vs则会强制报错。

int main()
{
	vector<int> v{ 1,2,3,4,5 };
	vector<int>::iterator it = find(v.begin(), v.end(), 3);
	v.erase(it);
	cout << *it << endl;
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
	return 0;
}

//程序正常运行,打印结果为
//4
//4 5

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

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

相关文章

Docker 在 Windows 上的使用指南

Docker 在 Windows 上的使用指南 Docker 是一种强大的容器化平台&#xff0c;广泛应用于开发和生产环境。本文将介绍如何在 Windows 系统上使用 Docker&#xff0c;包括容器的启动、常见问题的排查&#xff0c;以及网络问题的解决方法。 1. Docker 安装与配置 在开始使用 Do…

大模型书单指南:如何快速找到最适合你的那一本书?别找了就是这本!

大模型的书这么多&#xff0c;该怎么选呢&#xff1f; 本期书单就来教大家怎么快速地从众多大模型书中选到你想要的那一本&#xff01; 大模型基础 大模型入门不可错过的一本书&#xff0c;就是这本大模型界的经典畅销书**《大规模语言模型》**&#xff01;系统性强&#xf…

如何从 Mac 上清空的垃圾箱中恢复误删除的文件

在 Mac 上删除的文件将被移至垃圾箱并保留 30 天&#xff0c;然后才会被永久删除。但是&#xff0c;许多 Mac 用户可能会意外清空垃圾箱而没有意识到其中包含了重要文件。本指南包含从清空的垃圾箱中恢复 Mac 上已删除文件的所有有效方法。 当您意识到自己意外清空了 Mac 上的…

C语言基础(三十一)

1、线性搜索&#xff1a; #include "date.h" #include <stdio.h> #include <stdlib.h> #include <time.h> // 希尔排序 void shellSort(int arr[], int n) { for (int gap n / 2; gap > 0; gap / 2) { for (int i gap; i < n; i…

vue学习记录十四:路由(router)学习(五):Vue Router基本原理实现第二种方法

vue学习记录十四&#xff1a;路由&#xff08;router&#xff09;学习&#xff08;四&#xff09;&#xff1a;Vue Router基本原理实现二 一、vueRouter目录结构二、模拟vueRouter目录结构三、index.js文件实现四、install.js文件实现五、创建组件六、解析路由规则七、match实现…

浅谈人工智能之基于anaconda的AutoGen Studio环境搭建

浅谈人工智能之基于anaconda的AutoGen Studio环境搭建 AutoGen Studio 是一个基于 AutoGen 框架的图形用户界面&#xff08;GUI&#xff09;工具。它使开发人员能够更轻松地创建和管理多智能体应用&#xff0c;而无需编写代码。AutoGen Studio 提供了拖放式界面和各种预构建模…

绿色革命:‘众店‘如何重塑零售业并引领消费新潮流

在数字化浪潮的推动下&#xff0c;传统零售业正面临深刻的变革。在这一过程中&#xff0c;绿色积分系统作为一种创新的消费模式&#xff0c;逐渐成为市场的新宠。 一、"众店"平台的迅猛发展 "众店"平台仅用两年时间就实现了跨越式发展&#xff0c;交易额突…

JS基础【双重for循环的实现与应用、打印九九乘法表】

&#x1f680; 个人简介&#xff1a;某大型国企资深软件开发工程师&#xff0c;信息系统项目管理师、CSDN优质创作者、阿里云专家博主、华为云云享专家&#xff0c;分享前端后端相关技术与工作常见问题~ &#x1f49f; 作 者&#xff1a;码喽的自我修养&#x1f970; &#…

springboot+MySQL流浪猫狗疾病预约救治系统-计算机毕设 附源码 13676

springboot流浪猫狗疾病预约救治系统 摘 要 现如今在中国&#xff0c;随着人民生活质量的逐渐提高&#xff0c;以及人民群众消费能力的日渐增长&#xff0c;各种各样的家养小动物&#xff0c;已经逐渐成为人类越来越亲密的生活伴侣。并且&#xff0c;现如今社会竞争及其激烈&am…

钢铁百科:A633D交货状态、A633D对应牌号、A633D力学性能解析

A633D钢板是一种美标低合金高强度结构钢板&#xff0c;也被称为A633GrD钢板&#xff0c;其执行标准为ASTM/A633M。这种钢板以其高屈服强度、良好的韧性、抗腐蚀性和耐疲劳性而著称&#xff0c;广泛应用于建筑、桥梁、船舶、汽车、铁路、重型机械及矿山机械等多个领域。 一、A6…

【CSS】如何写渐变色文字并且有打光效果

效果如上&#xff0c;其实核心除了渐变色文字的设置 background: linear-gradient(270deg, #d2a742 94%, #f6e2a7 25%, #d5ab4a 48%, #f6e2a7 82%, #d1a641 4%);color: #e8bb2c;background-clip: text;color: transparent;还有就是打光效果&#xff0c;原理其实就是两块遮罩&am…

微信小程序知识点(一)

1.条件判断&#xff1a; wx:if&#xff0c;wx:elif&#xff0c;wx:else 和Hidden的区别 wx:if等是动态实现组件的&#xff0c;符合条件&#xff0c;页面上就新增一个组件&#xff0c;不符合&#xff0c;就会在也页面上加载&#xff0c;而Hidden只是控制页面的组件的显示与否&…

C#绘制常用工业控件(仪表盘,流动条,开关等)

目录 1&#xff0c;使用Graphics绘制Toggle。 效果&#xff1a; 测试代码&#xff1a; Toggle控件代码&#xff1a; 2&#xff0c;使用Graphics绘制Switch。 效果&#xff1a; 测试代码&#xff1a; Switch控件代码&#xff1a; 3&#xff0c;使用Graphics绘制PanelHe…

【Nest 学习笔记】AOP切片编程

切片编程 AOP 把通用逻辑抽离出来&#xff0c;通过切面的方式添加到某个地方&#xff0c;可以复用和动态增删切面逻辑。 中间件 Middleware Middleware 中间件属于全局中间件&#xff08;Middleware 是 Express 的概念&#xff09; 常用于对请求接口进行日志记录 // main.ts …

七. 部署YOLOv8检测器-load-save-tensor

目录 前言0. 简述1. 案例运行2. 补充说明3. 代码分析3.1 main.cpp3.2 create_data.py 结语下载链接参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考 本次课程我们来学习课程第六章—部署分类器&…

GMeLLo:结合知识图谱的 LLM 多跳问答技术,效果显著提升

1. GMeLLo 提出的背景 1.1 多跳问答 多跳问答的难度往往比较大&#xff0c;因为不仅要追溯事实&#xff0c;还要聚合与串联事实。 事实的来源可以是知识图谱、表格、自由格式文本&#xff0c;或者是这些来源的异构组合。 随着大型语言模型的发展&#xff0c;基于提示的方法…

安科瑞ACR10R网络电力仪表 CE认证 带外置互感器

产品概述&#xff1a; ‌‌安科瑞ACR10R网络电力仪表是一种集成了多种电力参数测量、电能计量、电能监测和考核管理等多种功能于一体的电力仪表。它适用于冶炼、钢铁、电焊、半导体等高能耗行业的节能改造工程&#xff0c;同时也适用于分布式光伏并网柜的功率监测、电力需求侧…

sqli-labs靶场通关攻略 56-60

主页有sqli-labs靶场通关攻略 1-55 第五六关 less-56 步骤一&#xff1a;闭合方式&#xff1a;?id1)-- 步骤二&#xff1a;查询数据库 ?id-1) union select 1,2,database() -- 步骤三&#xff1a;联合查询 查出网站的数据库表名 ?id-1) union select 1,2,group_concat(t…

探索AntSKPro AI知识库一体机:离线智能的便捷之选

在数字化时代&#xff0c;信息的获取和处理速度是企业和个人效率的关键。然而&#xff0c;网络连接的不稳定性常常成为阻碍。AntSKPro AI知识库一体机&#xff0c;一款专为离线环境设计的智能设备&#xff0c;以其卓越的性能和用户友好的设计&#xff0c;正在重新定义离线AI解决…

双指针--优选算法

个人主页&#xff1a;敲上瘾-CSDN博客 个人专栏&#xff1a;游戏、数据结构、c语言基础、c学习、OJ题 前言&#xff1a; 该篇文章我们主要来学习的是双指针算法&#xff0c;对于该类算法我们可以直接来做题&#xff0c;从题中去感知该算法的魅力&#xff0c;最后再从题中做总…