迭代器失效(附案例详解)

Posted xiao zhou

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了迭代器失效(附案例详解)相关的知识,希望对你有一定的参考价值。


本文将使用具体案例来详细解读迭代器失效的各种原因

迭代器指向内容意义改变

下面我们看一段代码

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);
	//查找3迭代器的位置
	vector<int>::iterator pos = find(v.begin(), v.end(), 3);	
	if (pos != v.end())
	{
		v.insert(pos, 10);		//在3之前插入10
	}
	PrintVector(v);
	v.erase(pos);
	PrintVector(v);
	return 0;
}

在3之前插入10后,我们又想将pos位置的3删除掉。
可是问题来了,这样的代码真的可以按照我们的想法进行吗?在我们执行代码后,我们发现并没有发生我们所预期的结果

jjfiah很明显,这样的代码是错误的,而这里错误的原因就是迭代器意义改变的一种迭代器失效。
jjfiah那么具体的错误是如何发生的呢?答案就是,在我们进行insert后,pos将不会再指向3,而是指向刚刚插入的10。

jjfiah假如说,插入之前pos的值是0x11223344,在插入10后,由于3-5这些数字要往后挪动,于是10就被放置在原先3的位置,而pos并没有随着3位置的改变而改变,因此,pos指向的就是10。pos代表的含义就变了

总结

这是一种原理较为简单的迭代器失效。就是在序列式容器中,由于插入/删除数据,导致迭代器所指的内容发生改变,而编写代码者没有即使发现该问题而导致的迭代器失效。

“野指针”类型的迭代器失效

下面我们看这样一段代码

int main()
{
	vector<int> v = { 1, 2, 3, 4, 5, 6 };
	//查找3迭代器的位置
	vector<int>::iterator pos = find(v.begin(), v.end(), 3);	
	if (pos != v.end())
	{
		v.insert(pos, 10);		//在3之前插入10
	}
	PrintVector(v);
	v.erase(pos);
	PrintVector(v);
	return 0;
}

这段代码与上一个代码类似,但是在执行时却发生了报错

jjfiah我们很容易注意到vector erase iterator outside range这段文字。内容含义是,vector在erase时,出现了越界错误。那么为什么会出现这种错误呢?

总结

在对序列式容器进行增删数据时,可能会发生容器的增容/缩容,或者越界操作时。就会涉及开辟新的空间,释放旧的空间或者越界访问。这时就会使迭代器指向一块未知的空间,就会发生迭代器失效。

两种迭代器失效合在一起的例子

jjfiah首先先来看下面的代码,代码的目的是删除一串数字中的奇数。

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<int>::iterator it = v.begin();
	while (it != v.end())
	{
		if (*it % 2 == 0)
			v.erase(it);
		it++;
	}

	return 0;
}


但是结果发生了内存错误。那么这种错误是怎么发生的呢?我们通过调试+走读代码可以分析出原因。原因如下:

1、在这里还出现的第一种情况,就是当erase掉it指向的内容后,由于vector是一种顺序型容器,it指向的内容不再是被删除的内容,而是被删除内容之后的内容。所以再次it++就会跳过一个元素。
2、这里it指向了vector之外的内容,就是野指针类型的迭代器失效。

解决方案


erase的返回值是删除位置的下一个元素的迭代器。所以当我们用it接收返回值时,it就直接是下一个元素的迭代器,就不需要it++等操作了。同时,也不会出现野指针的情况。

以上是关于迭代器失效(附案例详解)的主要内容,如果未能解决你的问题,请参考以下文章

Python进阶:一文搞懂迭代器生成器协程(附案例)

[C/C++]详解STL容器3--list的功能和模拟实现(迭代器失效问题)

重要朴素贝叶斯分类器详解及中文文本舆情分析(附代码实践)

[C/C++]详解STL容器2--vector的功能和模拟实现(迭代器失效,memcpy拷贝问题)

[C/C++ -STL]vector使用及迭代器失效问题详解

迭代器失效问题