C++——vector在使用过程中迭代器失效的几个常见情景

        在使用vector的时候我们可以会遇到需要在已有对象的某个数据之前插入一个数据再对被插入的数据进行修改操作,情况如下:

        这段代码在编译器的过程中并不会出现问题,可是一旦运行程序就会出现程序崩溃,这里就是迭代器失效的第一种情况:当我们在找到找到某个位置的时候,实际上找到的是这个数据所在的地址,我们insert操作本质上是把所有的数据往后移动了一个位置,把这个位置空出来,再把我们想要插入的数据插入到这个位置上,当insert函数结束的时候,it这个迭代器指向的还是之前的那个位置,但是这个位置所代表的数据已经改变了,所以vs的编译器进行了强制的检查,发现这个迭代器指向的数据已经发生了改变,让这个迭代器失效了,所以程序发生了崩溃。

int main()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.reserve(6);vector<int>::iterator it = find(v.begin(), v.end(), 2);if (it != v.end()){v.insert(it, 5);}*it *= 10;for (auto x : v){cout << x << " ";}return 0;
}

       

        第二种迭代器失效的情况和第一种很类似,但是发生在容器需要进行扩容的时候,假如这里我们自己实现了一个insert函数,这个insert函数的功能和库里的函数功能一致,也是在指定位置之前加上指定的数据,如果我们没有对指定位置的这个迭代器进行处理,如果正好碰到对象需要扩容的时候,程序也会出现错误。

        因为当对象的容量不够的时候,我们要在堆的另外一块空间上申请一块更大的空间,把原本对象里的数据拷贝到新的空间里,再回收原来的空间。这个时候问题就出现了,it迭代器指向的还是旧空间的位置,而我们的对象已经移动到了一个新的空间,这个时候插入数据就出现问题了,这是第一个问题,这个问题可以在insert函数里用it迭代器于对象begin迭代器的相对距离来解决。

        解决了上面的问题以后,main函数里的it迭代器还是指向的是旧空间的位置,但是这个位置的空间已经被释放掉了,所以这个迭代器也就变成了类似于野指针的存在。      

int main()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);vector<int>::iterator it = find(v.begin(), v.end(), 2);if (it != v.end()){v.insert(it, 5);}*it *= 10;for (auto x : v){cout << x << " ";}return 0;
}

        第三种迭代器失效的情况是发生在删除数据的时候,如果在使用迭代器的方式删除某个位置的数据以后,想要更改进入这个位置的数据时,也会出现程序的崩溃。

        这个崩溃的原因和第一个问题出现的原因是类似的,也是因为迭代器指向的位置的意义发生的改变,我们删除这个数据的本质是把这个数据之后的所有数据向前移动一位,这样要删除的数据就会被覆盖,实现被删除的效果,也是因为这个原因,虽然it原本指向的那个位置的数据已经被删除了,但是it这个迭代器还是指向这个位置,并没有消失,但是这个位置的意义已经发生改变了,vs环境下的代码进行了强制检查,所以程序出现了崩溃。同时不仅是这个it迭代器失效了,如果还存在指向被删除位置之后的迭代器,那么这些迭代器也都一并失效了。

int main()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);//v.reserve(6);vector<int>::iterator it = find(v.begin(), v.end(), 2);if (it != v.end()){v.erase(it);}*it *= 10;for (auto x : v){cout << x << " ";}return 0;
}

        所以如果在使用迭代器方式对容器进行插入或者删除以后,就最好不要再操作这个迭代器了,因为这个迭代器在大多数情况下都会失效,如果还想要使用这个迭代进行操作的话,可以对这个迭代器进行一次赋值,如下:

    vector<int>::iterator it = find(v.begin(), v.end(), 2);if (it != v.end()){it = v.insert(it, 5);}vector<int>::iterator it = find(v.begin(), v.end(), 2);if (it != v.end()){it = v.erase(it);}

        要注意的是insert的返回值是指向被插入的那个位置,也就是指向新插入的数据;erase的返回值则是被数据删除之前,被删除的位置的下一个数据,也就是重新进入被删除的位置的数据。

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

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

相关文章

如何使用 HTTPie 进行高效的 HTTP 请求

如何使用 HTTPie 进行高效的 HTTP 请求 引言 HTTPie 是一个命令行 HTTP 客户端&#xff0c;它以其简洁的语法和人性化的输出格式赢得了广大开发者的喜爱。与 curl 相比&#xff0c;HTTPie 提供了更加直观和用户友好的接口&#xff0c;使得执行 HTTP 请求变得轻松愉快。本文将…

PVE环境中调整虚拟机磁盘大小

我的希望将PVE中的虚拟机磁盘调整一下&#xff0c;增加20GB。在查询了一些资料后&#xff0c;做一下总结教程。 环境是 PVE8.2.2 版本&#xff0c;虚拟机系统是centos7.9.2009-minimal&#xff0c; 安装系统时划分磁盘分区方式是默认分区方式&#xff08;不同分区方式下&#…

pinia安装及简介

pinia简介 基本特点 轻量级&#xff1a;Pinia相比于传统的Vuex&#xff0c;体积更小&#xff0c;性能更好&#xff0c;只有大约1KB左右。 简化API&#xff1a;Pinia简化了状态管理库的使用方法&#xff0c;抛弃了Vuex中的mutations&#xff0c;只保留了state、getters和actions…

WHAT - 一个 Github 仓库的 License 如何解读

目录 一、背景二、解读许可证说明的作用常见的开源许可证类型使用他人代码仓库时需要注意的事项结论 实践作为开发者1. 选择许可证类型2. 在 README 文件中编写许可证信息 作为使用者1. 确定权限2. 了解和遵守条款 总结 一、背景 我们经常在一些 Github 仓库里看到 License 部…

探索 `pyjwt`:Python 中的 JWT 处理专家

文章目录 探索 pyjwt&#xff1a;Python 中的 JWT 处理专家简介&#xff1a;为何选择 pyjwt&#xff1f;什么是 pyjwt&#xff1f;安装 pyjwtpyjwt 的基本使用1. 编码JWT2. 解码JWT3. 验证签名4. 过期时间5. 自定义头部 场景应用场景一&#xff1a;用户登录场景二&#xff1a;A…

使用标量函数实现 EF Core 的实用方法

一.介绍 在构建应用程序时&#xff0c;您可能使用标量函数在数据库端实现一些逻辑。在 SQL 中&#xff0c;标量函数是一种对单个值或少量输入值进行操作并始终返回单个值作为输出的函数。这些函数本质上是可重复使用的代码块&#xff0c;用于对数据执行计算或操作。 以下是标…

商品中心关于缓存热key的解决方案

缓存热key一旦被击穿&#xff0c;流量势必会打到数据库&#xff0c;如果数据库崩了&#xff0c;游戏直接结束。 从两点来讨论&#xff1a;如何监控、如何解决。 如何监控 通过业务评估&#xff1a;比如营销活动推出的商品或者热卖的商品。基于LRU的命令&#xff0c;redis-cl…

doccano安装与使用

1.安装 &#xff08;1&#xff09;创建虚拟环境 conda create -n doccano conda activate doccano &#xff08;2&#xff09;安装doccano pip install doccano &#xff08;3&#xff09;doccano初始化 doccano init doccano createuser --username admin --password pa…

Java整理20

1、数据校验 Validation数据校验&#xff08;1&#xff09;实现org.springframework.validation.Validator接口&#xff0c;在代码中调用这个类&#xff08;2&#xff09;按照BeanValidation方式来校验&#xff0c;通过注解方式&#xff08;3&#xff09;基于方法实现校验&…

chk是什么文件格式 chk文件怎么恢复正常 chkdsk文件损坏怎么修复

在使用电脑和移动存储设备时&#xff0c;有时我们会发现磁盘中出现了大量的chk文件。这些chk文件无法打开&#xff0c;也无法得知其原本内容。那么&#xff0c;这些chk文件是什么呢&#xff1f;又该如何将chk文件恢复正常呢&#xff1f; chk文件是什么&#xff1f; 在我们查看…

Cocos Creator2D游戏开发-(2)Cocos 常见名词

场景&#xff08;Scene): 它一个容器&#xff0c;容纳游戏中的各个元素&#xff0c;如精灵&#xff0c;标签&#xff0c;节点对象。它负责着游戏的运行逻辑&#xff0c;以帧为单位渲染这些内容。就是你理解到的那个场景; 个人理解就是一个画面, 一个游戏不同的关卡,会有不同的…

【前端 12】js事件绑定

JavaScript 事件绑定 在Web开发中&#xff0c;事件绑定是实现用户与网页交互的重要机制。JavaScript 提供了多种方式来绑定和处理事件&#xff0c;使得开发者能够灵活地控制网页的行为。本文将详细介绍JavaScript中事件绑定的两种主要方式&#xff0c;并通过实例演示如何应用这…

Python+Pytest+Allure+Yaml+Pymysql+Jenkins+GitLab运行原理

PythonPytestAllureYamlPymysqlJenkinsGitLab运行原理逻辑及调用关系 GitLab代码仓&#xff1a; Jenkins工作空间&#xff1a; 代码&#xff1a; 测试报告展示&#xff1a;

<Python><paddle>基于python使用百度paddleocr实现车牌识别

前言 paddleocr是百度飞桨的一个文字识别库&#xff0c;准确度非常高&#xff0c;基于其文字识别的基础&#xff0c;将其用于车牌识别。这个识别的准确度是相当高的。 环境配置 系统&#xff1a;windows 平台&#xff1a;visual studio code 语言&#xff1a;python 库&#…

计算机网络知识点面试总结4

#来自ウルトラマンゼロ&#xff08;赛罗&#xff09; 1 传输层提供的服务 1.1 功能 传输层向它上面的应用层提供通信服务&#xff0c;它属于面向部分的最高层&#xff0c;同时也是用户功能中的最底层。 为运行在不同主机上的进程之间提供了逻辑通信。 传输层的功能&#xff1…

基于Gunicorn + Flask + Docker的高并发部署策略

标题&#xff1a;基于Gunicorn Flask Docker的高并发部署策略 引言 随着互联网用户数量的增长&#xff0c;网站和应用程序需要能够处理越来越多的并发请求。Gunicorn 是一个 Python WSGI HTTP 服务器&#xff0c;Flask 是一个轻量级的 Web 应用框架&#xff0c;Docker 是一…

react中如何避免父子组件同时渲染(memo的使用)

1.需求说明 react的渲染机制是父子组件同时渲染&#xff0c;不管子组件是否有变化只要父组件重新渲染了子组件就跟着重新渲染。为了避免不必要的消耗&#xff0c;我们可以使用memo钩子函数 2.使用memo前展示 import { memo,useState } from "react"function Son()…

20240728 每日AI必读资讯

Google Gemini 聊天机器人更新 可以免费使用Gemini 1.5 Flash 1. 引入Gemini 1.5 Flash模型&#xff1a; • 提供更快和更高质量的响应。 • 提升推理和图像理解能力。 • 上下文窗口扩大到 32Ktokens&#xff0c;允许进行更长的对话和处理更复杂的问题。 • 即将支持通过 Goo…

【数据结构】常用数据结构的介绍:理解与应用

文章目录 前言一、介绍二、使用场景三、总结 前言 在计算机科学中&#xff0c;数据结构是我们组织和存储数据的方式&#xff0c;它可以帮助我们高效地执行各种操作&#xff0c;如搜索、插入和删除。从数组和链表&#xff0c;到树和图&#xff0c;不同的数据结构有着不同的优点…

深入理解计算机系统 CSAPP 练习题12.4

我们每次都用read_set初始化ready_set是因为我们每次都处理read_set里的描述符,这是我们希望服务器做的事情.每次一有描述符3或描述符0,select函数会更新ready_set ,我们判断更新后ready_set的情况.然后干对应的事. 由此可以看到select函数的神奇之处,它把一个复杂的事情简单化…