关于C++迭代器失效问题

迭代器失效问题


所谓迭代器失效就是原有的空间被销毁,而继续用迭代器来进行访问,导致程序崩溃。
我们以vector为例来讲解迭代器失效问题

增加元素

对于原有的空间被销毁,除了主动释放,那就只有扩容的时候才可能发生的事。
扩容的时候,会释放原有的空间,并且会开辟新空间,并把原有空间里的数据拷贝到新空间里面去,此时,迭代器对应的指针所指向的空间不再属于自己的,造成经典的野指针问题。
那么这一类问题怎么解决呢?
只需要把迭代器对应的指针重新赋值就行:

#include<iostream>
#include<vector>

using namespace std;

int main()
{
	int a[] = { 0,1,2,3,4,5,6,7,8,9 };
	int sz = sizeof(a) / sizeof(a[0]);

	vector<int> v(a,a + sz);
	vector<int>::iterator it = v.begin();

	v.push_back(10);
	it = v.begin();//扩容之后迭代器就要重新赋值,如果没有,就报错

	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	return 0;
}

如果上面这段代码不能很好的展现,还有下面这段:

int main()
{
	int a[] = { 1,2,3,4,5,6,7,8,9 };
	int sz = sizeof(a) / sizeof(a[0]);

	vector<int> v(a, a + sz);
	vector<int>::iterator pos = find(v.begin(), v.end(), 3);
	//v.insert(pos, 30);//如果用这行代码,不用下面这行代码,也会导致野指针问题,因为pos位置没有更新
	pos = v.insert(pos, 30);

	vector<int>::iterator it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

	(*pos)++;
	for (auto ch : v)
	{
		cout << ch << " ";
	}
	cout << endl;

	return 0;
}

删除元素

当然,并不是只有释放原有空间开辟新空间才会出现迭代器失效问题,删除数据也会,有朋友可能会想了:删除怎么可能会造成迭代器失效,又没有销毁空间?
删除前面几个还好,如果删除的是最后一个呢?
在这里插入图片描述
如果仅仅只是删除8那还没事,可是如果还要对pos位置进行操作的话就出问题了,这也是一个野指针问题,所以删除之后迭代器还是要更新的。
接下来看看这段代码:

int main()
{
	int a[] = { 1,2,3,4 };
	int sz = sizeof(a) / sizeof(a[0]);

	vector<int> v(a, a + sz);
	//删除所以偶数
	vector<int>::iterator pos = v.begin();
	while (pos != v.end())
	{
		if (*pos % 2 == 0)
		{
			v.erase(pos);
		}
		pos++;
	}	

	for (auto ch : v)
	{
		cout << ch << " ";
	}
	cout << endl;
	return 0;
}

这段代码是有问题的,问题出在哪呢?
在这里插入图片描述
首先删除之前是这个样子的,但是代码中,无论是否遇到偶数,都会++,所以会导致下面这张图的局面:
![在这里插入图片描述](https://img-blog.csdnimg.cn/cc0b7613d5874e31b846b2b9f9bb4e83.p
这个时候就已经开始出现问题,换一种情况,如果是连续的偶数,那就会发生跳过,导致后面那个偶数没有被删除。
后面还有更严重的:
此时pos指向的数据是4,要先删除:
在这里插入图片描述
再++:
在这里插入图片描述

此时,它们就已经错过了,再来看这个循环结束条件,是!=,所以造成死循环。
怎么改进呢?
其实只需要解决删除数据后pos位置的更新就行:

int main()
{
	int a[] = { 1,2,3,4 };
	int sz = sizeof(a) / sizeof(a[0]);

	vector<int> v(a, a + sz);
	//删除所以偶数
	vector<int>::iterator pos = v.begin();
	/*while (pos != v.end())
	{
		if (*pos % 2 == 0)
		{
			v.erase(pos);
		}
		pos++;
	}*/

	while (pos != v.end())
	{
		if (*pos % 2 == 0)
		{
			pos = v.erase(pos);
		}
		else
		{
			pos++;
		}
	}

	for (auto ch : v)
	{
		cout << ch << " ";
	}
	cout << endl;
	return 0;
}

所以,我们在用迭代器的时候如果进行了增加删除的操作,还是要把迭代器更新一下。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值