在实际的应用中,会碰到需要遍历容器中的元素,并且在判断某些的条件后,将某个元素从容器中清除的场景:

#include <stdio.h>

#include <map>
#include <set>
#include <list>
#include <vector>
#include <deque>

template<class T>
void del(T t, int pos)
{
	// 测试循环遍历中的删除操作
	int i = 0;
	for (typename T::iterator it = t.begin(); it != t.end(); ++i)
	{
		printf("%d ", *it);
		if (i == pos)
		{
			t.erase(it++);
		}
		else
			++it;
	}
	printf("\n");
}

int main()
{
	std::map<int, int> mp;
	std::set<int> st;
	std::list<int> lt;
	std::vector<int> vec;
	std::deque<int> dque;

	for (int i = 0; i < 10; ++i)
	{
		mp.insert(std::make_pair(i, i));
		st.insert(i);
		lt.push_back(i);
		vec.push_back(i);
		dque.push_back(i);
	}

	del(mp, 5);
	del(st, 5);
	del(lt, 5);
	del(vec, 5);
	del(dque, 5);

	return 0;
}


注意上面的代码,it++或者++it,并不是发生在for循环头里面,而是在for循环体内,而当要进行删除时,应该使用

t.erase(it++);

it++这个重载操作会使it后移,并返回当前迭代位置。

运行上面的代码后,map、set、list正确输出了值,而当运行到vec或者dque后,会发生断言崩溃等情况,原因是执行erase后,it已经无效,导致下次循环时,取值失败。

因此需要注意以上这种循环遍历中删除元素,且不影响继续遍历的方式可以用于关系容器中(map,list,set等),而线性容器(vector,deque等)就会出现问题。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐