【c++】——详解迭代器失效的底层原理

一、迭代器为什么会失效

在讲解这个问题之前,我们来模拟一些场景。

场景一:把vec容器中所有的偶数全部删除
代码实现如下:

vector<int> vec;
	for (int i = 0; i < 20; i++)
	{
   
		vec.push_back(rand() % 100 + 1);
	}
	auto it = vec.begin();
	for (; it != vec.end(); ++it)
	{
   
		if (*it % 2 == 0)
		{
   
		vec.erase(it);
		break;
		}
	}

如果有break,运行结果如下:
在这里插入图片描述
表示只删除一个迭代器,没有问题

如果没有break,运行结果如下:
在这里插入图片描述
发现进程意外中断,进程不是正常结束运行——迭代器失效问题,第一次调用erase过后,迭代器it就失效了。
因为,对一个已经失效的迭代器,再进行加加的时候代码就会产生不可预期的错误,是一个非法的操作

场景二:给vec容器中所有的偶数前面添加一个小于偶数值1的数字
代码实现如下:

vector<int> vec;
	for (int i = 0; i < 20; i++)
	{
   
		vec.push_back(rand() % 100 + 1);
	}
auto it = vec.begin();
	for (; it != vec.end(); ++it)
	{
   
		if (*it % 2 == 0)
		{
   
			vec.insert(it,*it-1);
			break;
		}
	}
}

有无break的效果同场景一一样。
通过以上两个场景的分析,我们可以总结出迭代器失效原因:

  1. .当容器调用erase方法后,当前位置到容器末尾元素的所有迭代器全部失效,如下图:
    在这里插入图片描述

  2. 当容器调用insert方法后,当前位置到容器末尾元素的所有迭代器全部失效,如下图:
    在这里插入图片描述

  3. insert来说,如果引起容器扩容。原来容器的所有迭代器就全部失效了,因为连内存都改变了

  4. 不同容器的迭代器是不能进行比较运算的

二、如何解决迭代器失效问题

解决方案是,对插入/删除点的迭代器进行更新操作,去当前元素增加一个元素,或者将当前失效的迭代器删除,将新的iterator返回

例如,上述场景一,改进如下:

vector<int> vec;
	for (int i = 0; i < 20; i++)
	{
   
		vec.push_back(rand() % 100 + 1);
	}
auto it = vec.begin();
	while (it != vec.end())
	{
   
		if (*it % 2 == 0)
		{
   
			it = vec.erase(it);//对迭代器进行更新
		}
		else
		{
   
			++it;
		}
	}

运行结果如下:
在这里插入图片描述
场景二改进如下:

vector<int> vec;
	for (int i = 0; i < 20; i++)
	{
   
		vec.push_back(rand() % 100 + 1);
	}
auto it = vec.begin();
	for (; it != vec.end(); ++it)
	{
   
		if (*it % 2 == 0)
		{
   
			it = vec.insert(it, *it - 1);
			++it;
		}
	}
	for (int v : vec)
	{
   
		cout << v << " ";
	}
	cout << endl;

三、剖析迭代器失效底层原理

1、成员变量vector<T, Alloc>* _pVec

首先,我们要在iterator类的private里面添加一个成员变量vector<T, Alloc>* _pVec;
他的作用是让迭代器知道当前迭代器迭代的是哪个容器对象,所以给迭代器提供一个指向当前容器对象的指针
有了该指针过后,我们就可以去对!=,++和*运算符进行重载了。

(1)比较运算符重载
检查迭代器的有效性,如果为空,则代表该指针指向的容器是空的表示迭代器失效了。
还有两个不同对象的迭代器比较是没有意义的

bool operator!=
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值