C++:迭代器失效问题

目录

1.vector迭代器失效问题

1.底层空间改变

​编辑 2.指定位置元素的删除操作

2.Linux下的迭代器失效检测

1.扩容

2.删除

3.解决方法


1.vector迭代器失效问题

        迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了封装 ,比如: vector 的迭代器就是原生态指针 T* 。因此 迭代器失效,实际就是迭代器底层对应指针所指向的 空间被销毁了,而使用一块已经被释放的空间 ,造成的后果是程序崩溃 ( 如果继续使用已经失效的迭代器, 程序可能会崩溃 )
在C++中,当一个vector进行了插入或删除操作时,其迭代器可能会失效。这是因为在插入或删除操作之后,vector可能会重新分配内存空间,导致原来的迭代器指向的位置不再有效。
可能会导致其迭代器失效的操作有

1.底层空间改变

1. 会引起其底层空间改变的操作,都有可能是迭代器失效 ,比如: resize reserve insert assign 、push_back等。
#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<vector>int main()
{vector<int> v;v = { 1,2,3,4,5,6 };auto it = v.begin();//使用reserve扩容,可能会引起底层容量的改变,旧空间释放,但是it依旧使用的时释放前的旧空间v.reserve(100);while (it != v.end()){cout << *it << " ";++it;}return 0;
}
我们使用resize reserve insert assign、 push_back等操作都可能会导致扩容, 也就是说vector底层原理旧空间被释放掉, 而在打印时,it还使用的是释放之间的旧空间,在对it迭代器操作时,实际操作的是一块已经被释放的 空间,而引起代码运行时崩溃。
如果我们在扩容后重新赋值即可解决这个问题,可以继续操作it迭代器。

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

#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<vector>int main()
{vector<int> v;v = { 1,2,3,4,5,6 };//auto it = v.begin();//使用reserve扩容,可能会引起底层容量的改变,旧空间释放,但是it依旧使用的时释放前的旧空间//v.reserve(100);auto it = v.begin();while (it != v.end()){v.erase(it);  //删除it位置的数据,导致迭代器失效//这时再对it进行操作就是非法访问cout << *it << endl;++it;}return 0;
}

如图中代码,运行会崩溃

erase 删除 pos 位置元素后, pos 位置之后的元素会往前搬移,没有导致底层空间的改变,理论上讲迭代器不应该会失效,但是:如果pos 刚好是最后一个元素,删完之后 pos 刚好是 end 的位置,而 end 位置是没有元素的,那么pos 就失效了。因此删除 vector 中任意位置上元素时, vs 就认为该位置迭代器失效了。

如果在删除后对迭代器it重新赋值,这个时候就不会失效,因为erase返回删除元素下一个位置元素的迭代器。

2.Linux下的迭代器失效检测

Linux 下, g++ 编译器对迭代器失效的检测并不是非常严格,处理也没有 vs 下极端。

1.扩容

运行如下代码:

 

可以运行但是结果已经出错。

2.删除

运行如下代码

可以正常运行,erase删除任意位置代码后,linux下迭代器并没有失效 因为空间还是原来的空间,后序元素往前搬移了,it的位置还是有效的

但是如果删除的是最后一个元素呢

程序崩溃,因为删除最后一个元素,删除后it已经超过end,++it导致程序崩溃

3.解决方法

vector 类似, string 在插入 + 扩容操作 +erase 之后,迭代器也会失效
迭代器失效解决办法:在使用前,对迭代器重新赋值即可

1.在进行插入或删除操作之后,更新迭代器的位置,使其指向有效的元素。

2.在进行插入或删除操作之前,先将迭代器保存下来,然后再进行操作之后重新定位迭代器。

3.另外,C++11引入了emplace_back()和emplace()函数,它们可以在vector中直接构造对象,而不是先创建临时对象再插入,这样可以减少迭代器失效的可能性 

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

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

相关文章

前端使用css去除input框的默认样式

关键点&#xff1a; /* 关键点&#xff0c;让输入框无边框 */outline:none; border:none; 1.效果图 2.html <div class"container"><input type"text" placeholder"请输入用户名"><input type"text" placeholder&q…

145 删除链表的第N个节点的3种方式

问题描述&#xff1a;给定一个链表&#xff0c;删除链表的倒数第n个节点&#xff0c;并且返回链表的头结点。 栈求解&#xff1a;对于栈而言可以很好地解决链表只能从前往后访问的问题&#xff0c;栈是解决从后往前访问的利器。 public TreeNode deleteLastNNode(ListNode ro…

在命令提示符,csc不能使用,怎么办?

找到一个路径&#xff0c;"C:\Windows\Microsoft.NET\Framework64\v4.0.30319"&#xff0c;将此路径添加到环境变量。 在Windows 11里&#xff0c;Setting--About--Advanced System Settings--Environment Variables&#xff0c;双击Path。 PS C:\Users\a-xiaobodou…

Java算法 leetcode简单刷题记录5

Java算法 leetcode简单刷题记录5 老人的数目&#xff1a; https://leetcode.cn/problems/number-of-senior-citizens/ substring(a,b) 前闭后开 统计能整除数字的位数&#xff1a; https://leetcode.cn/problems/count-the-digits-that-divide-a-number/ 并不复杂&#xff0c;…

springboot+mysql校园社团信息管理系统-计算机毕业设计源码62756

目 录 摘要 第1章 绪论 1.1 研究背景 1.2 研究意义 1.3论文结构与章节安排 第2章 相关技术 ....... 2.1开发技术 2.2 Java简介 2.3 MVVM模式 2.4 B/S结构 2.5 MySQL数据库 2.6 SpringBoot框架介绍 第3章 系统分析 6 3.1 可行性分析 6 3.2 系统流程分析 6 3.3 …

前端JavaScript篇之JavaScript有哪些数据类型,它们的区别?

目录 JavaScript有哪些数据类型&#xff0c;它们的区别&#xff1f;数据类型区别 JavaScript有哪些数据类型&#xff0c;它们的区别&#xff1f; 数据类型 JavaScript数据类型有&#xff1a; Undefined、Null、Boolean、Number、String、Array、Object、Symbol、BigInt… St…

详解华为铁三角工作法完全解密.ppt

华为铁三角工作法是华为“以客户为中心”的思想在客户界面的集中体现。是一种以客户经理、方案经理和交付经理为核心的销售方法&#xff0c;将为客户服务所需要的主要能力&#xff0c;一直延伸到客户界面&#xff0c;并统一运作。 华为铁三角工作法的核心&#xff1a; - 让听…

CC工具箱使用指南:【现状规划用地变化检查(村规)】

一、简介 在规划工作中&#xff0c;有一个普遍性的需求&#xff0c;就是需要检查规划前后在用地上究竟发生了哪些变化。 这一点很重要&#xff0c;不仅是要展示给别人看&#xff0c;自己也要十分注意。 规划方案完成后&#xff0c;一定要进行用地变化的检查&#xff0c;曾经…

【Go】依赖包管理

查看已安装的包&#xff08;带着后边的三个点&#xff09; # 列出所有已安装的包 go list ...下载包 # 不指定版本下载 go get github.com/IBM/sarama删除包 go clean -i github.com/IBM/sarama 修改版本 # 删除包 go clean -i github.com/IBM/sarama # 指定版本下载 go ge…

centos根据文件内容进行全局搜索

centos根据文件内容进行全局搜索&#xff0c;全文搜索 grep -rnw ‘/path’ -e ‘pattern’ 递归 行号 精确 ‘路径’ 内容 例子&#xff1a; grep -rnw ‘/usr’ -e ‘告警方式配置’

定时任务组件Quartz

1.Quartz介绍 官网&#xff1a;Quartz Enterprise Job Scheduler 2.Quartz框架的使用思路 1&#xff09;job - 任务 - 你要做什么事&#xff1f; 2&#xff09;Trigger - 触发器 - 你什么时候去做&#xff1f; 3&#xff09;Scheduler - 任务调度 - 你什么时候需要去做什么…

23种设计模式概述

学习设计模式对我们有什么帮助&#xff1f; 1.提高代码质量和可维护性&#xff1a;设计模式是经过验证的解决方案&#xff0c;有助于解决常见的设计问题。使用设计模式可以减少代码冗余&#xff0c;增强代码的可读性和可维护性&#xff0c;并提高代码的可靠性。 2.提升开发效率…

NVM (Node Version Manager) 安装使用

博文目录 文章目录 管理工具安装使用 管理工具 GitHub, nvm-windows nvm-windows: Similar (not identical) to nvm, but for Windows 管理 Node.js 版本有多种工具可选择, 其中使用最广泛的是 nvm, 目前 72.3k Star, 不支持 Windows 系统, nvm-windows, 是其他大佬为 Windows…

C语言 存储类型 关键字

目录 一、C 程序中可用的存储类 二、C 语言部分关键字 1. sizeof关键字 2. sizeof 对变量名或者字面值可以不用括号&#xff0c;但是计算类型是必须要加括号的 3. sizeof 与 strlen 的区别 4. volatile关键字 一、C 程序中可用的存储类 概述&#xff1a;存储类定义 C 程序…

面试经典150题(90-92)

leetcode 150道题 计划花两个月时候刷完&#xff0c;今天&#xff08;第四十八天&#xff09;完成了3道(90-92)150&#xff1a; 90.&#xff08;108. 将有序数组转换为二叉搜索树&#xff09;题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排…

深入Amazon S3:实战指南

Amazon S3(Simple Storage Service)是AWS(Amazon Web Services)提供的一项强大的云存储服务,广泛用于存储和检索各种类型的数据。本篇实战指南将深入介绍如何在实际项目中充分利用Amazon S3的功能,包括存储桶的创建、对象的管理、权限控制、版本控制、日志记录等方面的实…

ubuntu安装kibana

1、安装elastic search7 参考&#xff1a;elastic search入门-CSDN博客 2、安装kibana&#xff0c;版本对不上&#xff0c;不匹配&#xff0c;不能正常启动。 kibana要改成7.11.1版本的试试。 nohup wget https://artifacts.elastic.co/downloads/kibana/kibana-7.11.1-linu…

从0开始学习C++ 第一课:你的第一个C++程序

第一课&#xff1a;你的第一个C程序 当然可以。让我们从C的基础开始&#xff0c;我们的第一课将覆盖以下几个主题&#xff1a; 程序结构编写和运行你的第一个C程序基本的输入输出&#xff08;I/O&#xff09; 第一课&#xff1a;你的第一个C程序 在C中&#xff0c;所有的程…

Spring-配置文件

一、引子 了解完Spring的基本概念后&#xff0c;我们紧接着来了解Spring中的核心文件--Spring配置文件。 二、配置Bean 我们在上一节Spring的基本概念中快速使用了一下Spring&#xff0c;其中我们在配置文件中主要涉及到就是Bean标签的配置&#xff1a;主要的配置字段有id, …

Servlet系列:生命周期(init、 service、destroy)详解

Servlet的生命周期是由Web容器&#xff08;如Tomcat&#xff09;管理的&#xff0c;包括以下三个阶段&#xff1a; 加载和实例化&#xff1a;当Web应用程序启动时&#xff0c;Web容器会加载和实例化Servlet。加载和实例化过程可以在应用程序启动时自动完成&#xff0c;也可以通…