IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> vector迭代器失效分析 -> 正文阅读

[C++知识库]vector迭代器失效分析

1.迭代器简介

迭代器(iterator)是STL库的一大组件,它可以让我们更为便利的对容器中的元素进行操作。从使用层面上讲,它的操作十分类似于指针。例如我们可以使用解引用操作,取得迭代器位置的元素。或者是自增操作,让迭代器指向下一个元素。

在vector容器中,迭代器的底层实际就是指针变量。因为vector本身在物理层面就是线性结构,所以可以很好的和指针的操作兼容。

但是,我们在使用迭代器时,常常会遇到迭代器失效的情况。一旦迭代器失效,就可能出现各种意想不到的错误,下面,我们就来分析迭代器失效的原因,以及迭代器失效的解决办法。

2.insert操作导致的迭代器失效

我们在使用insert函数对vector容器进行操作时,需要进行如下调用:

iterator insert (iterator position, const value_type& val);

而迭代器失效就是指传入的position迭代器在经过insert操作后变得不可用。

举个例子:

int main()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);//v有三个元素 1,2,3

	vector<int>::iterator it = find(v.begin(),v.end(),3);
    //找到3并用迭代器it记录该位置

	v.insert(it, 8);//在3的位置插入一个8
	cout << *it << endl;//输出it位置的元素
	return 0;
}

运行上面这段代码,我们会发现程序崩溃了。这是为什么呢?

因为在insert时,vector可能需要进行扩容,而扩容的本质是new一块新的空间,再将数据迁移过去。而我们知道,迭代器的本质是指针,而插入后,若vector扩容,则原有的数据被释放,指向原有数据的迭代器就成了野指针,所以迭代器失效了。

而解决的办法很简单,insert函数提供了返回值,这个返回值是指向插入之后的val的迭代器。我们只需要保存返回的迭代器,并使用这个新的迭代器即可。

另外,插入操作会导致所有的迭代器失效,因为所有的数据都被迁移,原空间的所有迭代器都成了野指针。

3.erase操作导致的迭代器失效

使用erase函数删除指定迭代器位置的元素,需要进行如下调用:

iterator erase (iterator position);

下面我们用一个例子来说明erase产生的迭代器失效:

int main()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(1);
	v.push_back(1);
	v.push_back(1); //此时v的元素为 1,1,1,1
	vector<int>::iterator it0 = v.begin();
	vector<int>::iterator it1 = v.begin() + 1;
	vector<int>::iterator it2 = v.begin() + 2;
	vector<int>::iterator it3 = v.begin() + 3;//四个迭代器分别指向下标为0 1 2 3的元素
	v.erase(it2);//erase掉it2迭代器位置的元素
	cout << *it0 << endl;
	cout << *it1 << endl;
	cout << *it2 << endl;
	cout << *it3 << endl;//对四个迭代器指向的元素进行输出
	return 0;
}

我们逐语句进行调试,会发现,it0和it1的值是可以打出来的,而到了it2,程序就会崩溃。

那么,这是为什么呢?其实,在erase后,VS编译器会判定迭代器失效,因为迭代器位置的元素被删除后,不再指向删除前的元素,所以迭代器失效了。故程序运行到输出it2位置,就崩溃了。

int main()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(1);
	v.push_back(1);
	v.push_back(1); 
	vector<int>::iterator it0 = v.begin();
	vector<int>::iterator it1 = v.begin() + 1;
	vector<int>::iterator it2 = v.begin() + 2;
	vector<int>::iterator it3 = v.begin() + 3;
	v.erase(it2);
	cout << *it0 << endl;
	cout << *it1 << endl;//q去掉了删除it2位置元素的操作
	cout << *it3 << endl;
	return 0;
}

接着,我们把输出it2的语句删除,但是我们运行到输出it3所指向的元素时,程序仍然崩溃了。这是因为,删除操作后,由于删除位置后面的数据都要向前挪一位,导致了删除位置后面的迭代器所指向的元素都发生了变化,所以处于it2位置之后的it3,也在所难免的失效了。

解决erase操作导致的迭代器失效的办法也很简单,erase同样会返回一个迭代器,这个迭代器指向了在erase操作前,被删除元素的下一个元素的新位置。所以,我们进行erase操作后,直接使用这个返回的迭代器即可。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-16 22:04:24  更:2022-03-16 22:06:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:09:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码