vector的erase函数的陷阱

博客探讨了在C++中使用`std::vector::erase`删除元素后,迭代器失效的问题。作者遇到的错误是尝试在删除元素后继续使用已失效的迭代器。正确的做法是使用`erase`的返回值更新迭代器。调试时在Debug模式下会立即捕获错误,而在Release模式下可能会导致更严重的后果。解决方案是确保在删除元素后立即更新迭代器。

 在下面的代码中,我试图用erase删除vector中的所有值为偶数的元素。根据c++primer 11,erase的返回值是指向被删除元素之后元素的迭代器。根据我的想法,我认为既然是删除一个元素,那么该被删除元素之后的所有元素都会往前移动一个位置,因此在删除该元素后,指向该被删除元素的迭代其器变成指向下一个元素的迭代器,但是却出现了错误。晚上的解答是使用erase(p)之后,p变为无效状态。

有问题的代码:

#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <deque>
using namespace std;

int main()
{
	int a[] = { 0,1,1,2,3,5,8,13,21,55,89 };
	vector<int> vi(begin(a), end(a));
	//list<int> li(begin(a), end(a));
	auto it1 = vi.begin();
	while (it1 != vi.end())
	{
		if (*it1 % 2 == 0)
		{
			vi.erase(it1);
		}
		else
		{
			++it1;
		}
	}
	for (auto v : vi) cout << v << " ";
	return 0;
}

正确代码:

#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <deque>
using namespace std;

int main()
{
	int a[] = { 0,1,1,2,3,5,8,13,21,55,89 };
	vector<int> vi(begin(a), end(a));
	//list<int> li(begin(a), end(a));
	auto it1 = vi.begin();
	while (it1 != vi.end())
	{
		if (*it1 % 2 == 0)
		{
			it1 = vi.erase(it1);
		}
		else
		{
			++it1;
		}
	}
	for (auto v : vi) cout << v << " ";
	return 0;
}

然而这个回答没有消除我的疑问,因为在单步调试时出现了下面的情况,似乎每一步都是合理的,指向被删除的元素的迭代器确实成为指向下一个元素的迭代器。

it1指向0元素,0将被删除

元素0被删除。 it1指向1。目前执行到if语句。再往下执行一步(也就是执行该if语句)就报错了,但是此时it1确实是有效的,让人十分费解。。。有空在琢磨一下吧,在此记录一下这个问题。

---------------------------------------------------------------------------------------------------------------------------------

最近在知乎上看到了一条答案:在debug模式下使用失效的迭代器会报错,在realease下不会报错,但可能造成更加严重的后果。

c++标准库是如何实现迭代器失效的? - rayhunter的回答 - 知乎 先mark一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值