STL:迭代器失效问题总结

写在前面

向容器中添加元素和从容器中删除元素的操作可能会使指向元素的指针,引用或迭代器失效。一个失效的指针,引用或者迭代器将不再表示任何元素。使用失效的指针,引用或迭代器是一种严重的程序设计错误,很可能引起与使用未初始化指针一样的问题。

向容器添加元素后:

1.对于vector 或者 string
如果存储空间被重新分配,则指向容器的迭代器,指针和引用都会失效。
如果存储空间未重新分配,指向插入位置之前元素的迭代器,指针和引用仍有效,但指向存在的元素的引用和指针不会失效。

2.对于deque
插入到除首尾位置之外的任何位置都会导致迭代器,指针和引用失效。
如果在首尾位置添加元素,迭代器会失效,但指向存在的元素的指针和引用不会失效。

3.对于list和forward_list
指向容器的迭代器(包括尾后迭代器和首前迭代器),指针和引用仍有效。

当我们从一个容器中删除元素后,指向被删除元素的迭代器,指针和引用会失效,这应该不会令人惊讶。毕竟,这些元素都已经被销毁了。当我们删除一个元素后

1.对于list和forward_list
指向容器其它位置的迭代器,引用和指针仍有效。

2.对于deque
如果在首尾之外的任何位置删除元素,那么指向被删除元素外的其它元素的迭代器,引用和指针都会失效。

如果删除deque的尾元素,则尾后迭代器也会失效,但其它迭代器,指针和引用不受影响;如果删除首元素,这些也不会受影响。

3.对于vector和string
指向被删元素之前的迭代器,引用和指针仍有效。

注意:使用失效的迭代器,指针或引用是严重的运行时错误。因此必须保证每次改变容器的操作之后都正确的重新定位迭代器。这个建议对于vector,string和deque尤为重要。

最后,补充一下前几天遇到一个关于Vector迭代器的经典例题:

vector<int>array;
	array.push_back(100);
	array.push_back(300);
	array.push_back(300);
	array.push_back(300);
	array.push_back(300);
	array.push_back(500);
	vector<int>::iterator itor=array.begin();
	while (itor != array.end())

	{
		if (*itor == 300)
		{
			itor = array.erase(itor);
		}
		
			++itor;
	}

	for (auto& v : array)
	{
		cout << v << endl;
		//cout << typeid(v). name();
	   
	}

	

}

执行结果:
STL:迭代器失效问题总结_第1张图片

思考一下原因?
STL:迭代器失效问题总结_第2张图片
因为vector的erase()操作会返回下一个元素的迭代器。注意是元素而不是位置。

理论上对vector进行移动、增加、插入、删除等操作均有可能导致空间重新配置,前三者引起空间重新配置很容易理解,csdn上也有很多这方面的论述,而删除操作引起迭代器失效容易,引起空间重新配置却并不多见,size会改变,空间却不会重新配置。

我们可以修改一下代码,再观察:

vector<int>array;
	array.push_back(100);
	array.push_back(300);
	array.push_back(300);
	array.push_back(300);
	array.push_back(300);
	array.push_back(500);
	vector<int>::iterator itor=array.begin();
	while (itor != array.end())

	{
		if (*itor == 300)
		{
			itor = array.erase(itor);
		}
		else                     
			++itor;
	}

	for (auto& v : array)
	{
		cout << v << endl;
		//cout << typeid(v). name();
	   
	}

	//相比之前就函数体内部多了一个 else 

}

执行结果:
STL:迭代器失效问题总结_第3张图片
这样就按需删除了全部的元素。

你可能感兴趣的:(C/C++)