vector迭代器失效的问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Ferlan/article/details/86423563

当你使用vector容器时,如果你进行下面2种中的任意一种操作:

  1. vector已满再进行插入操作
  2. 使用erase()删除数据.

就会导致迭代器失效.

为什么呢?

我们举个列子

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

int main()
{	
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(6);
	//给vector中插入6个数据.	
	
	auto e = v.begin();
	v.insert(v.end(), 7);//再用insert
	
	while (e != v.end())
	{
		cout << *e<<" ";
		e++;
	}
	
	system("pause");
	return 0;
}

比如上面的程序,给v插入6个数据,在插入第七个数据后,用迭代器遍历v就出现了错误.

下图是调试的截图,当我们插入6个数后,vector已经被填满,在要插入7时,就要对vector进

行扩容,而我们又知道,vector扩容的原理是:开辟一块更大的空间,将原空间数据腾到新的

空间,在释放源空间.这个操作过程中,迭代器始终没有发生变化,这就意味这,你扩容完毕

后,迭代器仍然指向着你释放掉的空间,此时再对迭代器进行++操作就会引发错误.

在这里插入图片描述

在这里插入图片描述

解决办法就是在扩容之后在重新定位迭代器,就不会有问题了.

第二种情况是进行erase()操作

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

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(), 3);//返回3位置的迭代器
	v.insert(it, 30);//3前面插入30
	it = v.begin();

	while (it != v.end())//删掉所有的偶数
	{
		if (*it % 2 == 0)
		{
			v.erase(it);
		}
		it++;
	}
	auto e = v.begin();
	while (e != v.end())
	{
		cout << *e<<" ";
	}
	
	system("pause");
	return 0;
}

上述程序的作用是vector中所有的偶数,那这次有是为什么导致了迭代器失效呢?我们来画图理解一下:

while (it != v.end())//删掉所有的偶数
	{
		if (*it % 2 == 0)
		{
			v.erase(it);
		}
		it++;
	}

在这里插入图片描述

我们发现,在删除偶数的过程中3被跳过了,没有被检查是否是偶数,这是因为erase的底层

实现是后面的元素向前挪覆盖掉被删除元素所导致的,当我们以为迭代器正常迭代时,其

实它已经失效了,最可怕的是,当最后一个元素4被检查删除后,迭代器还要进行++操作,因

为逻辑上此时它还不是end(),但end()其实前挪了,所以迭代器又跑到了vector的外面,导致

出现错误.

解决办法:
erase(iterator it)函数的返回值是被删除元素的下一个有效位置的迭代器,所以我们将这个值赋给迭代器就不会有问题了.

while (it != v.end())//删掉所有的偶数
	{
		if (*it % 2 == 0)
		{
			it = v.erase(it);
		}
		else
		{
			it++;
		}
	}

猜你喜欢

转载自blog.csdn.net/Ferlan/article/details/86423563