vector迭代器失效

目录

迭代器失效的场景

insert插入元素时迭代器失效

erase删除元素时迭代器失效


本期我们主要进行vector迭代器失效问题的讨论。

迭代器失效的场景

insert插入元素时迭代器失效

先看代码:

iterator insert(iterator pos, T val)
		{
			assert(pos >= _start);
			assert(pos <= _finish);
			size_t length = pos - _start;
			if (_finish == _endofstorage)
			{
				reserve(capacity() == 0 ? 4 : capacity() * 2);
			}
			pos = _start + length;
			iterator end = _finish - 1;
			while (end >= pos)
			{
				*(end + 1) = *end;
				end--;
			}
			_finish--;
			*pos = val;
			return pos;
		}

insert插入元素时为什么会导致迭代器时效呢?其实这主要是在插入元素时,空间不够,扩容导致的。

 解析:如图,假设在pos位置插入一个元素,但是此时空间不够,所以我们进行了扩容。但是扩容之后此时的pos仍然指向了之前的位置,所以此时的pos就已经失效了(这就称作迭代器失效),所以我们得通过pos-_start的值计算出来pos位置与_start的位置,然后在扩容之后,通过差值计算出来真正的pos的位置。需要注意的是,我们此时的正确位置只是形参里pos的正确位置,但是实参是没有发生变化的,因为insert形参列表中的pos位置传的是实参pos的值,所以我们得通过返回值的方式返回扩容后正确的pos位置。

erase删除元素时迭代器失效

 我们要删除vector中的偶数元素,此时erase失效场景有三种:

第一种:

解析:思想:我们要删除所有的偶数所以先让pos指向第一个元素的位置,如果不是偶数就 + +如果pos位置的元素是偶数就删除pos 位置的元素,删除元素的思想其实就是把要删除的元素的后面的所有元素统一往前移动一个位置,这样就删除了要删除的元素。对于第一种情景,我们发现,确实是删除了所有的偶数。
注意: end表示最后一个元素的位置的下一个位置。 

第二种:

解析:跟第一种情景的思想是一样的,但是到最后会产生迭代器失效,在删除了元素之后,我们会先将指向了删除了的元素的位置的指针+ +,然后再将finish--但是这样会产生一种极端的情况,如图,就是当最后一个元素是偶数时,我们将最后一个元素删除之后,先将指向了最后一个元素的指针++,然后将finish--,这就导致了pos和 finish错位,因为循环的终止条件是pos<_finish,因为pos和 finish错位,这就导致循环不会终止,所以这种情况是有问题的。

第三种:

解析:这种情景我们称作连续偶数的情景,在这种情景下,同样是因为,我们再删除完了元素之后先++了pos,因为删除的本质就是将删除位置的元素后面的所有元素统一往前移动一格位置,就会导致要删除的位置的元素被删除之后,要删除的元素的下一个元素就自动的移动到了要删除的元素的位置上,但是我们仍然++pos,就会导致删除的元素的下一个元素被无意间跳过,这就导致了要删除的元素的下一个元素永远无法删除,这便是这种情景没有完全删除所有的偶数元素的原因。 

在这三种情形下迭代器都已经失效了,那么我们该怎样去进行代码的修改呢?直接代码:

iterator  erase(iterator pos)
		{
			assert(pos >= _start);
			assert(pos < _finish);

			iterator begin = pos;
			while (begin < _finish - 1)
			{
				*begin = *(begin + 1);
				begin++;
			}
			--_finish;
			//这里要返回pos位置上的数据,是因为,可能会跳过元素,这里有几种情况,所以我们必须返回删除之后,正确的迭代器的位置,所以我们要返回pos
			// 1 2 3 4 5 -> 正常
			// 1 2 3 4   -> 崩溃
			// 1 2 4 5   -> 没删除完
			return pos;
		}

这是删除元素的代码,我们用迭代器作为返回值的原因是因为,要返回删除的元素的下一个元素的位置,但是因为删除的思想,会导致要删除的元素后面的所有元素统一往前移动一个位置,所以要删除的元素的下一个元素的位置其实就是pos位置。 

原始版本:

void test1()
	{
		vector<int> v1;
		v1.pushback(1);
		v1.pushback(2);
		v1.pushback(4);
		v1.pushback(5);
	    vector<int>::iterator pos= v1.begin();
		while (pos != v1.end())
		{
			if (*pos % 2 == 0)
			{
				v1.erase(it);
			}

			++pos;
		}
	}

每次删掉元素都要进行迭代器的++,导致迭代器失效。 

改进版本:

void test1()
	{
		vector<int> v1;
		v1.pushback(1);
		v1.pushback(2);
		v1.pushback(4);
		v1.pushback(5);
		vector<int>::iterator pos =v1.begin();
		while (pos != v1.end())
		{
			if (*pos % 2 == 0)
			{
				pos = v1.erase(pos);
			}
			else
			{
				++pos;
			}
		}
	}
}

改进了之后,再删除掉元素之后,不直接++,而是返回要删除的元素的下一个元素的位置作为pos迭代器的值(采用这种方式的原因吗,其实还要为缩容去考虑,不然完全可以删除完之后不返回任何值)。 

编译器缩容场景的迭代器失效很少见到,所以我们就不做介绍。

本期内容到此结束^_^

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

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

相关文章

springboot农机电招平台源码和论文

随着农机电招行业的不断发展&#xff0c;农机电招在现实生活中的使用和普及&#xff0c;农机电招行业成为近年内出现的一个新行业&#xff0c;并且能够成为大群众广为认可和接受的行为和选择。设计农机电招平台的目的就是借助计算机让复杂的销售操作变简单&#xff0c;变高效。…

React(3): React 实现卖座App

React实现卖座App 娱乐项目&#xff0c;请勿当真 &#xff01;&#xff01;&#xff01; 简介 之前在学习React的时候&#xff0c;在 bilibili 看到 React 学习视频&#xff0c;于是马上着手 React版本的卖座App 开发 技术栈 // 前端 React TypeScript Antd-Mobile Dayjs 3D…

《Linux高性能服务器编程》笔记08

Linux高性能服务器编程 本文是读书笔记&#xff0c;如有侵权&#xff0c;请联系删除。 参考 Linux高性能服务器编程源码: https://github.com/raichen/LinuxServerCodes 豆瓣: Linux高性能服务器编程 文章目录 Linux高性能服务器编程第08章 高性能服务器程序框架8.1 服务器…

Redis——list以及他的应用场景

介绍 &#xff1a;list 即是 链表。链表是一种非常常见的数据结构&#xff0c;特点是易于数据元素的插入和删除并且且可以灵活调整链表长度&#xff0c;但是链表的随机访问困难。许多高级编程语言都内置了链表的实现比如 Java 中的 LinkedList&#xff0c;但是 C 语言并没有实现…

如何学习VBA_3.2.12.13:VBA中工作表函数的利用

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的劳动效率&#xff0c;而且可以提高数据处理的准确度。我推出的VBA系列教程共九套和一部VBA汉英手册&#xff0c;现在已经全部完成&#xff0c;希望大家利用、学习。 如果…

JavaScript进阶:WebAPIs重点知识整理1

目录 1 DOM修改元素内容 2 DOM修改元素常见属性 3 修改元素样式属性 3.1 通过style修改元素样式 3.2 通过类名className修改元素样式 3.3 通过classList修改元素样式 4 操作表单元素属性 5 自定义属性 6 定时器 7 事件监听 7.1 点击事件 click 7.2 鼠mouseenter和移…

Web网页生成桌面应用

前言&#xff1a;网页生成桌面指的是将一个网页保存为桌面应用程序的形式&#xff0c;使得用户可以在桌面上直接打开该网页&#xff0c;而不必通过浏览器打开。这种桌面应用程序一般具有独立的窗口、菜单、工具栏等界面元素&#xff0c;能够提供更加方便快捷的使用体验。 实现…

Vue 动态组件与异步组件:深入理解与全面应用

聚沙成塔每天进步一点点 本文内容 ⭐ 专栏简介1. 动态组件实现原理&#xff1a;用法示例&#xff1a; 2. 异步组件实现原理&#xff1a;用法示例&#xff1a; 3. 异步组件的高级应用a. 异步组件的命名&#xff1a;b. 异步组件的加载状态管理&#xff1a; ⭐ 写在最后 ⭐ 专栏简…

目标检测算法改进系列之添加C2f-DCN模块

DCNv2简介 可变形卷积网络的卓越性能源于其适应物体几何变化的能力。通过对其自适应行为的检查&#xff0c;我们观察到&#xff0c;虽然对其神经特征的空间支持比常规的 ConvNet 更接近对象结构&#xff0c;但这种支持可能远远超出感兴趣区域&#xff0c;导致特征受到不相关图…

使用KMP迁移Android app到IOS平台

使用KMP迁移Android app到IOS平台 如果你有一款Android app&#xff0c;你想将其迁移到IOS平台&#xff0c;但是你不熟悉Swift语言&#xff0c;那么你该如何做呢&#xff1f;辛亏JetBrains 推出 Kotlin Multiplatform 和 Compose Multiplatform &#xff0c;突然间&#xff0c…

代码随想录算法训练营第十六天| 104.二叉树的最大深度 ● 111.二叉树的最小深度 ● 222.完全二叉树的节点个数

104.二叉树的最大深度 本题可以使用前序&#xff08;中左右&#xff09;&#xff0c;也可以使用后序遍历&#xff08;左右中&#xff09;&#xff0c;使用前序求的就是深度&#xff0c;使用后序求的是高度。 ●二叉树节点的深度&#xff1a;指从根节点到该节点的最长简单路径边…

Linux-Shell脚本基础

一、前言&#xff1a; 1.程序编程风格&#xff1a; 面向过程语言&#xff1a; 开发的时候 需要 一步一步 执行 做一件事情&#xff0c;排出个步骤&#xff0c;第一步干什么&#xff0c;第二步干什么&#xff0c;如果出现情况A&#xff0c;做什么处理&#xff0c;如果出现了情…

DC-9靶机做题记录

靶机下载地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1LR44-oFnO6NU6bTNs7VNrw?pwdhzke 提取码&#xff1a;hzke 参考&#xff1a; 【DC系列靶机DC9通关讲解】 https://www.bilibili.com/video/BV1p24y1s78C/?share_sourcecopy_web&vd_source12088c392…

Fluent Bit配置与使用——基于版本V2.2.2

Fluent Bit日志采集终端 文档适用版本&#xff1a;V2.2 1、日志文件处理流程 数据源是一个普通文件&#xff0c;其中包含 JSON 内容&#xff0c;使用tail插件记录日志&#xff0c;通过parsers进行格式化匹配&#xff08;图里没写&#xff09;&#xff0c;通过两个筛选器&…

白酒:发酵过程中的化学反应与香气形成

云仓酒庄的豪迈白酒在发酵过程中经历了多种化学反应&#xff0c;这些反应对于酒的香气和口感的形成起到了至关重要的作用。 首先&#xff0c;我们要了解发酵的定义。发酵是一个生物化学过程&#xff0c;通过特定微生物的作用&#xff0c;将原料中的糖类物质转化为酒精和二氧化碳…

爬虫正则+bs4+xpath+综合实战详解

Day3 - 1.数据解析概述_哔哩哔哩_bilibili 聚焦爬虫&#xff1a;爬取页面中指定的页面内容 编码流程&#xff1a;指定url -> 发起请求 -> 获取响应数据 -> 数据解析 -> 持久化存储 数据解析分类&#xff1a;正则、bs4、xpath(本教程的重点) 数据解析原理概述&am…

JQuery下载和一些语法

最近学了六种jQuery选择器&#xff0c;我想把学过案例和知识结合起来&#xff0c;给大家分享下&#xff01; 那么既然学jQuery选择器&#xff0c;肯定要先了解下jQuery是什么吧&#xff01;jQuery是一个快速、简洁的JavaScript框架&#xff0c;相当于用jQuery能更加高效的创建…

男主角展现炸裂演技,演绎方式独具匠心,令人叹为观止

♥ 为方便您进行讨论和分享&#xff0c;同时也为能带给您不一样的参与感。请您在阅读本文之前&#xff0c;点击一下“关注”&#xff0c;非常感谢您的支持&#xff01; 文 |猴哥聊娱乐 编 辑|徐 婷 校 对|侯欢庭 在漫长的等待之后&#xff0c;《要久久爱》这部都市情感剧终…

Redis的主从复制

目录 一、主从复制 1.主从复制是什么 2. 主从复制能干嘛 3 主从复制 3.1创建一主二仆 3.2创建伪主从 3.3编写配置文件 3.4启动三台redis服器 3.5配置注册关系 4.复制原理 5.薪火相传 6.反客为主 7.哨兵模式(sentinel) 一、主从复制 1.主从复制是什么 主机数据更新…

服务器运维小技巧(二)——如何进行监控告警

服务器运维难度高的原因&#xff0c;很大程度是因为服务器一旦出现问题&#xff0c;生产环境的业务就会受到严重影响&#xff0c;极有可能带来难以承担的后果。因此这份工作要求工程师保持高要求的服务质量&#xff0c;能够快速响应问题&#xff0c;及时解决问题。 但是“及时…