关于vector的迭代器失效

news2024/11/28 10:45:15

目录

关于迭代器失效的判定

1 迭代器指向的位置是野指针(全部迭代器失效)

原因:

解决

2 erase或者insert之后迭代器被更改了(部分迭代器失效)

原因

迭代器失效的场景:

改进之后

部分迭代器失效之越界访问

原因

 解决

关于平台问题

总结


关于迭代器失效的判定

(在windows平台下)

1 迭代器指向的位置是野指针(全部迭代器失效)

原因:

容量的改变导致空间的重新分配

比如insert或者push_back这种往原先的vector中插入元素的操作,会进行一个容量的判断,如果容量满了就会扩容:扩容是深拷贝,扩容(reserve)的具体操作是这样子的

① 先判断当前空前和reserve之后空间的大小,如果reserve之后的空间大于现在的capacity会扩容

②新开辟一块reserve之后大小的tmp的空间

③将原先空间的值拷贝到新的空间

④将原先的空间释放

因此如果不对迭代器进行更新的话,迭代器仍然指向的是之前被释放的空间,会导致迭代器失效

图解

 

如果erase采取以时间换空间的做法:缩容

这种导致容量的改变的,并且迭代器没有及时更新的,就会导致对应的迭代器失效

解决

这种由于容量的改变引起的,只能在设计reserve的时候,同时更新迭代器的值才可以

void reserve(size_t newcapacity)
	{
		if (newcapacity > capacity())
			size_t sz = size();
			T* tmp = new T[newcapacity];
			if (_start)
			{
				memcpy(tmp, _start, sizeof(T) * size());
				delete[]_start;
			}
			_start = tmp;
			_end = _start + sz;
			_endofstorage = _start + newcapacity;

		
	}

2 erase或者insert之后迭代器被更改了(部分迭代器失效)

原因

在erase或者insert之后capacity并没有发生改变的一个情况

erase的底层实现:erase当前位置之后的值都会往前移动一个位置并且返回在erase之前的下一个位置的迭代器的值

insert的底层实现:insert当前位置之后的值都会往后移动一个位置,并且返回insert的pos位置的迭代器的值。 

不管是erase和insert和之前相比,pos和pos位置之后的迭代器都发生了变化,在windows下的vs判定下,就判定了对应的迭代器失效了。

 

 他是这样判定的:原先每个位置的迭代器分别指向1,2,3,4,5,6,7,8,在4的位置插入之后,原先4的位置变成了新插入的10,并且之后所有的元素都发生了移位,这样子的话,原先的迭代器指向的值就发生了改变,vs判定迭代器失效

erase也是同理的,erase 4位置的值之后,其后的元素会往前挪动覆盖,这样子的话,原先4的位置变成了5,并且之后的值都发生了改变,因此原先迭代器和之后的迭代器都失效了

解决:这种情况下,erase和insert的pos位置和之后的迭代器会失效,不去访问这些位置就可以了。

如果非得访问,记得更新一下迭代器的值

迭代器失效的场景:

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

int main()
{
	int ar[] = { 1,2,3,4,0,5,6,7,8,9 };
	int n = sizeof(ar) / sizeof(int);
	vector<int> v(ar, ar + n);
	vector<int>::iterator it = v.begin();
	while (it != v.end())
	{
		if (*it != 0)
			cout << *it;
		else
			v.erase(it);

		it++;
	}
	return 0;
}
	

改进之后

 

部分迭代器失效之越界访问

删除的值在这一组值的末尾

原因

为什么会导致迭代器失效呢?

最根本的原因是迭代器erase掉最后一个值之后返回的是最后一个元素下一个位置的迭代器,而非最后一个元素!

这样子的话返回的位置是没有元素的,属于非法访问。导致了迭代器的失效

 解决

如何避免呢?

可以将返回的迭代器重新赋值,将末尾的元素给它

 

关于平台问题

在windows的vs下,和在Linux下对比,由于底层实现和检查机制的不同,因此对于上述情况的运行是否报错也不尽相同

上述的情况都是在windows下进行讨论的,如果在Linux平台下的话,erase和insert一个位置,并且如果不是末尾的元素或者中间出现的连续的偶数,并且不引起底层空间的改变的情况下,是不报错的

如果是末尾的元素,和vs下的情况一样,也是属于一个非法访问,是会报错的

如果是删除连续的数字的话,结果是不太一样的,vs下是会直接报错,但是Linux下的话,运行是没问题的,就是结果会出错,会只能删除一个对应的元素,因为返回的是删除元素的下一个位置的迭代器,这样子的话,如果正常情况下迭代进行访问,会直接错过这个位置的值(不更新迭代器的话)

总结:

迭代器失效最根本是因为指向原先位置的迭代器在erase和insert的作用下发生了改变。但是对于不同的场景迭代器失效的原因也不尽相同:

涉及到容量的改变引起的全部迭代器失效

涉及到erase和insert的部分迭代器失效,erase的值如果在末尾的话的一种特殊的情况

避免迭代器失效的做法也差不多,就是重新更改迭代器的值,让他指向正确的值。

因此如果要避免迭代器失效的话,我们需要对reserve,insert和erase的底层实现非常了解才可以采取对应的措施。

并且在不同的平台下,迭代器是否失效以及失效带来的影响也是不同的。

所以我们平时对迭代器的使用,如果无法判断的话,最好就不要去访问删除之后的迭代器了,或者如果要解决迭代器失效的问题的话,一定要注意更新!

 

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

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

相关文章

十年前的AlexNet,今天的NeurIPS 2022时间检验奖

目录&#xff1a;十年前的AlexNet&#xff0c;今天的NeurIPS 2022时间检验奖一、前言二、时间检验奖一、前言 作为当前全球最负盛名的 AI 学术会议之一&#xff0c;NeurIPS 是每年学界的重要事件&#xff0c;通常在每年 12 月举办。大会讨论的内容包含深度学习、计算机视觉、大…

三款“非主流”日志查询分析产品初探

前言 近些年在开源领域&#xff0c;用于构建日志系统的软件有两类典型&#xff1a; Elasticsearch&#xff1a;基于 Lucene 构建倒排索引提供搜索功能&#xff0c;DocValue 存储支持了其统计分析能力。Clickhouse&#xff1a;列式存储是其优秀 OLAP 性能的保障。 这里把上述系…

Windows安装MySQL

目录 1、确认本地是否安装了mysql 2、下载安装包 3、安装mysql 4、修改mysql密码 5、配置环境变量 1、确认本地是否安装了mysql &#xff08;1&#xff09;按【winr】快捷键打开运行&#xff0c;输入services.msc&#xff0c;点击【确定】&#xff1b; &#xff08;2&…

大数据开发和软件开发哪个前景好?

大数据开发和软件开发哪个前景好&#xff1f;大数据开发学习有难度&#xff0c;零基础入门要先学习Java语言打基础&#xff0c;然后进入大数据技术体系的学习&#xff0c;学习Hadoop、Spark、Storm等知识。软件开发工程师根据不同的学科从事的岗位也千差万别。 先说说大数据开…

关于激光雷达传感器分类及简介

关于激光雷达传感器&#xff08;根据特性进行分类介绍&#xff09;0一些激光雷达的厂商总结1 基本介绍2 基本分类及组成2.1 激光雷达的相关分类2.1.1 机械式激光雷达&#xff1a;2.1.2 混合固态激光雷达&#xff1a;2.1.3 固态激光雷达&#xff1a;OPA和Flash固态激光雷达2.2 机…

Linux shell 脚本学习

目录 1.shell编程的基本格式 开头 注释 加可执行权限 执行脚本的三种方法 2.变量 定义变量和清除变量 从键盘获取值(read) 读取多个值 只读变量(readonly) 位置变量 变量运算 3.条件测试 文件测试 字符串测试 数值测试 逻辑操作符 4. if条件语句 if条件语句语法 单…

SPARKSQL3.0-源码剖析全流程导读

SPARKSQL-源码剖析全流程导读 一、处理流程 spark从一条sql语句一步一步转换成物理执行结果&#xff0c;这中间需要经历几个阶段&#xff0c;如下图&#xff1a; 二、各阶段概述 1、Unresolved-未解析阶段 此阶段主要做了两件事&#xff1a; 1、将sql字符串通过antrl4转化…

元数据管理系统

数据治理工具–元数据系统数据服务基础能力之元数据管理元数据管理系统设计 1.元数据概述 1.1 介绍 如果想建设好元数据系统&#xff0c;需要理解元数据系统的相关概念&#xff0c;如数据、数据模型、元数据、元模型、ETL、数据血缘等等。 首先&#xff0c;要清楚数据的定义…

python_函数

一、函数介绍组织好的&#xff0c;可重复使用的&#xff0c;用来实现特定功能的代码段例如&#xff1a;len() 函数--Python内置函数# 已组织好的、可重复使用&#xff0c;针对特定功能 def my_len(data):count 0for i in data:count 1print(f"字符串{data}的长度是{coun…

WebRTC实现一个网页在线录制视频

电脑录制视频几乎不会用到&#xff0c;当有需要的时候就各种找软件找工具&#xff0c;并且都会找免费的。现在市场上肯定有很多符合需求&#xff0c;只是那么偶尔的情况下&#xff0c;而且使用场景不是那么多要求的情况下&#xff0c;一个网页在线直接录屏是不是非常nice。 很…

40Java Runtime类

目录 Runtime类 1.概述 2.常见方法 (1).getRuntime返回环境对象 (2).exit停止虚拟机 (3).availableProcessors返回线程数 (4). maxMemory返回获得最大内存 (5).totalMemory返回已经获得内存 (6).freeMemory返回剩余内存 (7).exec运行cmd命令 Runtime类 1.概述 ​ Run…

双亲委派模型机制

文章目录类加载器findClassloadClassJDK双亲委派的破坏第一次破坏第二次破坏tomcat热部署JDK9最新改动双亲委派机制是当类加载器需要加载某一个.class字节码文件时&#xff0c;则首先会把这个任务委托给他的上级类加载器&#xff0c;递归这个操作&#xff0c;如果上级没有加载该…

卷积神经网络<二>keras实现多分支输入VGG

VGG的模型图 VGG使用Keras实现 这里的代码借鉴了VGG实现Keras&#xff0c;但是这段代码不支持多通道&#xff0c;并且vgg函数的扩展性不好。下面修改一下&#xff0c;方便进行多分支图片输入的建立&#xff0c;以及更见方便的调参。 # from keras.models import from keras.l…

MyBatis介绍

MyBatis介绍 MyBatis 是一款优秀的持久层框架&#xff0c;它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息&#xff0c;将接口和 Java 的 POJOs(Plain Ordi…

PMP考试自学可以吗?(含PMP备考资料)

当然是可以的&#xff0c;只要解决了“报考的35学时”这个问题&#xff0c;就只剩怎么备考的问题了。 在一般情况下&#xff0c;建议备考一到三个月&#xff0c;别给自己太长或太短的备考时间&#xff0c;前者坚持不下来&#xff0c;后者备考时间太少&#xff0c;来不及备考充…

戴尔大步进军经典量子计算混合模型

​ &#xff08;图片来源&#xff1a;网络&#xff09; 戴尔正将量子计算机融入传统IT的基础架构中&#xff0c;并向新型加速计算机开放了数据中心。这家服务器制造商为传统服务器基础设施创建了一个蓝图&#xff0c;以满足量子系统的独特需求&#xff0c;量子系统速度要比经典…

基于物联网的汽车爆胎预警系统

本设计是基于物联网的汽车爆胎预警系统的设计与实现设计&#xff0c;主要实现以下功能&#xff1a; 1&#xff0c;主机用LCD1602显示温度、气压和距离&#xff1b; 2&#xff0c;主从机间通过ZigBee进行数据的传输&#xff1b; 3&#xff0c;从机检测轮胎气压&#xff0c;温度…

zbxtable

ubuntu install zbxtable 1.新建zbxtable文件夹&#xff0c;将三件套下载到本地存放 mkdir ~/zbxtable ZbxTable: https://dl.cactifans.com/zbxtable/zbxtable-2.1.0.tar.gz ZbxTable-Web: https://dl.cactifans.com/zbxtable/web.tar.gz MS-Agent: https://dl.cactifans.co…

MybatisMybatisPlusSpringboot之最全入门学习教程笔记

1 Mybatis概述 1.1 Mybatis概念 MyBatis 是一款优秀的持久层框架&#xff0c;用于简化 JDBC 开发, &#xff08;1&#xff09;持久层&#xff1a;负责将数据到保存到数据库的那一层代码。Mybatis就是对jdbc代码进行了封装。 JavaEE三层架构&#xff1a;表现层、业务层、持久层…

ftp协议主动模式与被动模式

FTP主动模式与被动模式 主动模式&#xff1a;客户端给服务端的21控制端口发命令说&#xff0c;我要下载什么什么&#xff0c;并且还会说我已经打开了自己的某个端口&#xff0c;你就从这里把东西给我吧&#xff0c;服务器知道后就会连接客户端已打开的那个数据端口把东西传给客…