C++ 迭代器失效问题解决

 更新时间:2024年01月23日 15:52:44   作者:Faiz..  
在C++中,当一个vector进行了插入或删除操作时,其迭代器可能会失效,本文就来介绍一下C++ 迭代器失效问题解决,具有一定的参考价值,感兴趣的可以了解一下

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中直接构造对象,而不是先创建临时对象再插入,这样可以减少迭代器失效的可能性 

到此这篇关于C++ 迭代器失效问题解决的文章就介绍到这了,更多相关C++ 迭代器失效内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言数组与地址、数组名到底是什么详解

    C语言数组与地址、数组名到底是什么详解

    在写代码的时候,我们经常用到数组,那么有没有想过数组名是什么呢?这篇文章主要给大家介绍了关于C语言数组与地址、数组名到底是什么的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-06-06
  • 总结c++性能优化策略

    总结c++性能优化策略

    在本篇文章中小编给大家总结了关于C++的性能优化策略的相关知识点,对此有兴趣的朋友可以参考学习下。
    2018-03-03
  • opencv C++模板匹配的简单实现

    opencv C++模板匹配的简单实现

    这篇文章主要介绍了opencv C++模板匹配的简单实现,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-02-02
  • C++迭代器删除元素避免索引混乱问题及分析

    C++迭代器删除元素避免索引混乱问题及分析

    C++中删除容器元素时,索引操作易因内存变化导致混乱,而迭代器通过动态感知容器结构变化,提供更安全的删除方式,正确实践是用erase()返回值更新迭代器,优先使用remove_if算法,避免手动调整索引,确保遍历安全与代码通用性
    2025-09-09
  • 用C++实现推箱子小游戏

    用C++实现推箱子小游戏

    这篇文章主要为大家详细介绍了用C++实现推箱子小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • C语言接口与实现方法实例详解

    C语言接口与实现方法实例详解

    这篇文章主要介绍了C语言接口与实现方法,包括接口的概念、实现方法及抽象数据类型等,并配合实例予以说明,需要的朋友可以参考下
    2014-09-09
  • C++稀疏矩阵的各种基本运算并实现加法乘法

    C++稀疏矩阵的各种基本运算并实现加法乘法

    今天小编就为大家分享一篇关于C++稀疏矩阵的各种基本运算并实现加法乘法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-02-02
  • C/C++中字符串的存储方式详解

    C/C++中字符串的存储方式详解

    在C语言中,字符串通常以字符数组的形式存在,并以空字符(\0)结尾,在C++中,建议使用 std::string 类来处理字符串,本文给大家介绍了C/C++中字符串的存储方式,需要的朋友可以参考下
    2024-11-11
  • C语言中对字母进行大小写转换的简单方法

    C语言中对字母进行大小写转换的简单方法

    这篇文章主要介绍了C语言中对字母进行大小写转换的简单方法,是C语言入门学习中的基础知识,需要的朋友可以参考下
    2015-08-08
  • C++深入分析数据在内存中的存储形态

    C++深入分析数据在内存中的存储形态

    使用编程语言进行编程时,需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着,当您创建一个变量时,就会在内存中保留一些空间。您可能需要存储各种数据类型的信息,操作系统会根据变量的数据类型,来分配内存和决定在保留内存中存储什么
    2023-01-01

最新评论