vector迭代器失效list迭代器失效

news2025/2/8 1:03:39

目录

一、vector迭代器失效

1.1插入时的迭代器失效

1.2删除时的迭代器失效 

二、list迭代器失效

2.1删除时的迭代器失效


 在vector与list的模拟实现中,其中有一问题就是迭代器的失效问题,那么迭代器的失效问题具体是指什么,接下来一探究竟。

一、vector迭代器失效

1.1插入时的迭代器失效

 在插入元素发生扩容时按原生理解可以用以下图来表示。

但是如果要拷贝的元素里面也开了空间呢?

例如:vector中存的是string对象,那么在进行扩容时,开辟新空间,将原来元素拷贝到新的空间,然而要拷贝的string对象其成员也是开了空间,当我们采用浅拷贝时,发生的就是值拷贝,即string对象的指针拷贝给另一个string对象的指针,那么他们就会指向同一个空间,如下图:

 

从而当其中一个对象调用析构时,那么其指向的空间就会释放掉,当另一个对象调用析构时,而原来指向的空间已经被上一个对象呢给释放掉了,那么自己在释放已经释放的空间就会造成程序崩溃。这就造成了迭代器的失效

其中memcpy拷贝时发生的就是浅拷贝 :

void reserve(size_t n)
		{
 
			if (n > capacity())
			{
				size_t len = size();
				iterator tmp = new T[n];
				
				if (_start)
				{
					memcpy(tmp, _start, sizeof(T) * (_finish - _start));//浅拷贝
					
					delete[] _start;
				}
				
				_start = tmp;
				_finish = _start + len;
				_end_of_storage = _start + n;
			}
			
		}
		

 那么为了解决这个问题,就可以采用赋值的方式,因为赋值他是一种深拷贝,拷贝过去的成员会另外指向一个空间,那么在调用析构时就不会释放已经释放的对象了

赋值深拷贝: 

void reserve(size_t n)
		{
 
			if (n > capacity())
			{
				size_t len = size();
				iterator tmp = new T[n];
				
				if (_start)
				{
					//memcpy(tmp, _start, sizeof(T) * (_finish - _start));//浅拷贝
					for (int i = 0; i < len; i++)
					{
						tmp[i] = _start[i];
					}
 
					delete[] _start;
				}
				
				_start = tmp;
				_finish = _start + len;
				_end_of_storage = _start + n;
			}
			
		}
		

1.2删除时的迭代器失效 

对于erase的实现,在删除元素时,删除position位置的元素后,返回的还是当前position的迭代器,只不过position的迭代器不在指向原来的空间了,导致原来的迭代器就失效了,如下:

iterator erase(iterator position)
		{
			assert(position < size());
			if (size())
			{
				size_t len = _finish - position - 1;
				for (int i = 0; i < len; i++)
				{
					*(position + i) = *(position + i + 1);
				}
				--_finish;
			}
			return position;
		}

通过一张图来描绘: 

 

 通过例子来解释上述现象:

int main()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(6);

	auto it = v.begin();

	while (it != v.end())
	{
		if (*it == 3)
			it = v.erase(it);//删除迭代器位置指向的3,返回迭代器位置,此时迭代器指向的是4		
		else
			cout << *it << " ";
		it++;//这里再++,那么迭代器就指向了5去了
	}

	
	return 0;
}

 

二、list迭代器失效

对于list而言,其底层是连续的,那么插入元素时,不存在需要扩容的情况, 只是创建节点进行链接即可。但是,对于删除元素时还是跟vector一样存在迭代器的失效。

2.1删除时的迭代器失效

	iterator erase(iterator pos)
		{
			assert(pos != end());

			pNode cur = pos._node;
			pNode next = cur->_next;
			
			cur->_prev->_next = next;
			next->_prev = cur->_prev;
			
			delete cur;
			
			return next;
		}

 对于list的erase的实现,在删除元素时,删除pos位置的元素后,返回的还是当前pos的迭代器 ,只不过pos不在指向原来的空间了,导致原来的的迭代器就失效了,如下图:

 

通过例子来解释上述现象:

int main()
{
	list<int> l;
	l.push_back(1);
	l.push_back(2);
	l.push_back(3);
	l.push_back(4);

	auto it = l.begin();

	while (it != l.end())
	{
		if (*it == 2)
			it = l.erase(it);//删除迭代器位置指向的2,返回迭代器位置,此时迭代器指向的是3		
		else
			cout << *it << " ";
		it++;//这里再++,那么迭代器就指向了4去了
	}
	return 0;
}

 

对于以上迭代器的失效问题,总结就一句话,最好不要去使用已经删除过的迭代器 

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

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

相关文章

【C语言基础】:预处理详解(二)

文章目录 一、宏和函数的对比二、#和##运算符2.1 #运算符2.2 ##运算符 三、#undef四、命令行定义五、条件编译六、头文件的包含1. 头文件包含的方式2. 嵌套文件包含 上期回顾&#xff1a; 【C语言基础】&#xff1a;预处理详解(一) 一、宏和函数的对比 宏通常被应有于执行简单…

系统学c#:1、基础准备(软件下载与安装)

一、Vs软件下载与安装 访问Visual Studio官方网站&#xff1a; https://visualstudio.microsoft.com/zh-hans/downloads 下载Visual Studio 运行exe文件&#xff0c;点击“继续” 初始文件安装完成后选择我们需要安装的项&#xff0c;并勾选好必要的单个组件&#xff0c;设…

VisualStudio2010编译GDAL2.2.4

一、源码目录组织结构 makefile.vc文件是windows下nmake编译工具的makefile文件&#xff0c;nmake.opt是makefile文件的编译选项配置选择文件。 二、打开Visual Studio2010的64位命令行&#xff0c;切换到GDAL224的解压根目录下 输入如下命令回车开始编译源码 nmake -f makef…

Bitwarden 一款开源的密码管理器

Bitwarden Bitwarden 是一款开源的密码管理器&#xff0c;提供强大的安全性和便捷的密码管理功能。 适用于运维、系统较多、密码保密程度较高的场景&#xff01; 主要功能&#xff1a; 密码保存与自动填充&#xff1a;Bitwarden 可以安全地存储您的用户名和密码&#xff0c…

阿里云迁移到AWS云,九河云保姆级教程

随着云计算技术的不断发展,越来越多的企业开始将传统的IT基础设施迁移到云平台上,以获得更高的灵活性、可扩展性和成本效益。在众多云服务提供商中,阿里云和AWS都是备受青睐的选择。本文将探讨如何将阿里云上的资源顺利迁移到AWS云平台,并针对性地进行优化。我们九河云&#xf…

【第9章】@Autowired

文章目录 前言一、Autowired注入1. 属性注入2. 构造方法注入3. set方法注入4. 形参注入5. byName注入5.1 新增实现类5.2 注入 二、Resource1.引入库2.使用2.1 根据注解的name值注入2.2 根据对象变量名注入2.3 根据对象类型注入 总结 前言 【第8章】全注解开发介绍了全注解开发…

电竞陪玩系统开发平台搭建(小程序,公众号,app)线上线下皆有,线下计算距离。

六大核心功能 1.游戏陪练:可以选择当下火爆的游戏内容&#xff0c;选择游戏大神、职业玩家进行陪练&#xff0c;也可约附近路人玩家或是身边的小伙伴语音组队开黑&#xff0c;一起享受边玩游戏边吐槽的无限乐趣。 2.约玩交友:除了游戏陪玩功能&#xff0c;系统还设置了单独的语…

将自己的项目上传至Git

一、安装Git 官网:Git (git-scm.com) 二、注册gitee 官网:工作台 - Gitee.com 进入“我的”出现以下界面 三、创建仓库 点击加号&#xff0c;新建仓库 根据自己的需求取名&#xff0c;描述仓库&#xff0c;开源还是私有&#xff0c;点击创建即可&#xff0c;点击我的即可…

Linux学习-数据库

数据库软件: 关系型数据库: Mysql Oracle SqlServer Sqlite 非关系型数据库&#xff1a; Redis NoSQL 1.数组、链表、文件、数据库 数组、链表: 内存存放数据的方式(代码运行结束、关机数据丢失) 文件、…

一文掌握 React 开发中的 JavaScript 基础知识

前端开发中JavaScript是基石。在 React 开发中掌握掌握基础的 JavaScript 方法将有助于编写出更加高效、可维护的 React 应用程序。 在 React 开发中使用 ES6 语法可以带来更简洁、可读性更强、功能更丰富,以及更好性能和社区支持等诸多好处。这有助于提高开发效率,并构建出更…

MongoDB 索引全攻略

目录 一、索引介绍 1.1 单字段索引 1.2 复合索引 1.3 多键索引 1.4 主键索引 1.5 TTL 索引 1.6 地理空间索引 1.7 哈希索引 1.8 创建索引时注意事项 1.9 索引效果查看 二、索引实现原理 2.1 为什么使用 B-Tree 三、执行计划 一、索引介绍 任何数据库都有索引这一核心功能&…

Centos7.6部署minikube

1、什么是minikube ? Minikube是由Kubernetes社区维护的单机版的Kubernetes集群&#xff0c;支持macOS, Linux, and Windows等多种操作系统平台&#xff0c;使用最新的官方stable版本&#xff0c;并支持Kubernetes的大部分功能&#xff0c;从基础的容器编排管理&#xff0c;到…

基于AutoCAD的WMTS服务加载方法与应用研究

"针对在AutoCAD中加载地图存在数据定位操作复杂、数据渲染效率低、无法接入第三方地理信息服务的问题&#xff0c;提出了在AutoCAD中加载OGC标准的网络地图分块服务方法。基于ObjectARX二次开发插件&#xff0c;实现在AutoCAD中加载WMTS服务&#xff0c;兼容了第三方地理信…

基于Springboot的旅游管理系统

基于SpringbootVue的旅游管理系统的设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatis工具&#xff1a;IDEA、Maven、Navicat 系统展示 用户登录 首页展示 旅游方案展示 旅游资讯 后台管理员登录 后台管理页面首页 用户管理 …

【自动驾驶】贝叶斯算法在机器学习中的应用研究

目录 第一章&#xff1a;引言 1.1 贝叶斯算法在机器学习中的重要性 1.2 研究背景 1.3 研究目的 1.4 论文结构 第二章&#xff1a;贝叶斯算法概述 2.1 贝叶斯定理 2.2 贝叶斯算法分类 第三章&#xff1a;贝叶斯算法在机器学习中的应用 3.1 贝叶斯分类器 3.2 贝叶斯回…

SpringSecurity源码分析3--UserDetail部分

UserDetailsService.class DaoAuthenticationProvider.class AbstractUserDetailsAuthenticationProvider.class 一个允许子类重写和处理UserDetails对象的基AuthenticationProvider。该类旨在响应UsernamePasswordAuthenticationToken身份验证请求。 AuthenticationProvider…

Gartner 《2024安全和风险管理技术路线图》:高价值技术 DSP 进入广泛部署阶段

近期&#xff0c;Gartner 发布《2024年技术采用路线图&#xff1a;安全与风险管理》&#xff08;以下简称&#xff1a;《路线图》&#xff09;&#xff0c;该信息图表识别了全球企业正在采用的 44 种与安全相关的技术&#xff0c;并根据采用阶段、部署风险和企业价值进行了映射…

python中的列表、元组、字典、集合(字典篇)

数据类型定义符号访问元素是否可变是否重复是否有序列表 [ ]索引可变可重复有序元组&#xff08;&#xff09;索引不可变可重复有序字典{key&#xff1a;value}键可变可重复无序集合{ }可变不可重复无序 字典概念 在python语言中&#xff0c;字典属于内置容器类&#xff0c;其…

什么是云安全

云安全和网络安全有所不同&#xff0c;因为云安全一词 比网络安全更涵盖整个企业基础设施。一般来说&#xff0c;当人们提到云安全时&#xff0c;指的是第三方服务提供商提供的 IaaS 云环境。在这种情况下&#xff0c;云安全不仅包括网络安全工具&#xff0c;还包括服务器、容器…

C#基础|数据类型、变量

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 01 数据类型 数据类型是为了方便存储数据的&#xff0c;为了将数据按照不同的分类存储&#xff0c;所以引入数据类型。这个在PLC中已经很熟悉了。 数据类型的作用&#xff1a;就是为了更好地管理内存&#xff0c;为…