stl容器循环删除元素总结

程序中有一段代码是关于stl循环删除的内容,大体逻辑如下(实际逻辑要复杂的多,不适合用std::remove系列函数):

int main(int argc, char **argv)
{
	std::vector<int> vec{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	auto it_vec = vec.begin();
	while (it_vec != vec.end()) {
		if (*it_vec % 2 == 0) {
			vec.erase(it_vec++);
			continue;
		}
		++it_vec;
	}

	return 0;
}

尽管平常都是用std::remove系列函数,但印象中上面的代码也没有任何问题的,但是程序一运行却当掉了。原因是每次执行std::vector::erase之后,迭代器是失效,当再次执行it_vec != vc.end()时,程序当掉。具体原因:std::vector,std::string,std::deque等顺序存储的容器,插入删除操作均会是所有容器失效;std::list,std::map,std::set等非顺序存储的容器,执行删除操作仅会是当前迭代器失效,插入操作不会是任何迭代器失效。无论是顺序结构容器,还是非顺序结构容器,删除操作都会返回最后一个被删除元素的后一个迭代器。

因此,对于std::vector,std::string,std::deque而言,正确的循环删除操作如下:

int main(int argc, char **argv)
{
	std::vector<int> vec{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	auto it_vec = vec.begin();
	while (it_vec != vec.end()) {
		if (*it_vec % 2 == 0) {
			it_vec = vec.erase(it_vec);
			continue;
		}
		++it_vec;
	}

	std::string str("school college");
	auto it_str = str.begin();
	while (it_str != str.end()) {
		if (*it_str == 'o') {
			it_str = str.erase(it_str);
			continue;
		}
		++it_str;
	}

	std::deque<int> deq{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	auto it_deq = deq.begin();
	while (it_deq != deq.end()) {
		if (*it_deq % 2 == 0) {
			it_deq = deq.erase(it_deq);
			continue;
		}
		++it_deq;
	}

	getchar();

	return 0;
}

对于std::list,std::map,std::set等非顺序容器,正确的循环删除操作可以是下面的样子:

int main(int argc, char **argv)
{
	std::list<int> lst{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	auto it_lst = lst.begin();
	while (it_lst != lst.end()) {
		if (*it_lst % 2 == 0) {
			it_lst = lst.erase(it_lst);
			continue;
		}
		++it_lst;
	}

	std::map<int, char> mp{ { 0, '0' }, { 1, '1' }, { 2, '2' }, { 3, '3' }, { 4, '4' }, { 5, '5' }, { 6, '6' }, { 7, '7' }, { 8, '8' }, { 9, '9' } };
	auto it_mp = mp.begin();
	while (it_mp != mp.end()) {
		if (it_mp->first % 2 == 0) {
			it_mp = mp.erase(it_mp);
			continue;
		}
		++it_mp;
	}

	std::set<int> st{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	auto it_st = st.begin();
	while (it_st != st.end()) {
		if (*it_st % 2 == 0) {
			it_st = st.erase(it_st);
			continue;
		}
		++it_st;
	}

	getchar();

	return 0;
}

也可以是下面的样子:

int main(int argc, char **argv)
{
	std::list<int> lst{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	auto it_lst = lst.begin();
	while (it_lst != lst.end()) {
		if (*it_lst % 2 == 0) {
			lst.erase(it_lst++);
			continue;
		}
		++it_lst;
	}

	std::map<int, char> mp{ { 0, '0' }, { 1, '1' }, { 2, '2' }, { 3, '3' }, { 4, '4' }, { 5, '5' }, { 6, '6' }, { 7, '7' }, { 8, '8' }, { 9, '9' } };
	auto it_mp = mp.begin();
	while (it_mp != mp.end()) {
		if (it_mp->first % 2 == 0) {
			mp.erase(it_mp++);
			continue;
		}
		++it_mp;
	}

	std::set<int> st{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	auto it_st = st.begin();
	while (it_st != st.end()) {
		if (*it_st % 2 == 0) {
			st.erase(it_st++);
			continue;
		}
		++it_st;
	}

	getchar();

	return 0;
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值