昨天面试的时候,面试官突然问到这个问题,一面懵逼,感觉一样,回来试了一下,还真是不一样,做个小计。
STL中,关于vector rease的源码如下(其中以清除某个位置元素函数为例):
iterator rease(iterator position)
{
if (position + 1 != end())
copy(position + 1, finish, position);
--finish;
destroy(finish);
return position;
}
可以看到源码中返回的是一个迭代器类型,现在做一个测试,分别在windows和Linux下。
Windows下的vector erase
vector<int> ve = { 1, 2, 3, 4, 5 };
for (auto iter = ve.begin(); iter != ve.end(); ++iter)
{
cout << *iter << endl;
if (*iter == 3)
{
ve.erase(iter); //编译OK,运行会出现问题,迭代器失效
}
}
因为运行时,发现3这个元素并删除,此时迭代器失效变成野指针,如果要是在遍历过程中继续处理后面元素可以这样写。
vector<int> ve = { 1, 2, 3, 4, 5 };
for (auto iter = ve.begin(); iter != ve.end(); ++iter)
{
cout << *iter << endl;
if (*iter == 3)
{
ve.erase(iter); //出现野指针
//方法1:返回删除元素的下一个位置,指向4,但是for中又有一个++,没有验证第四个元素
//iter = ve.erase(iter);//返回删除元素的下一个位置
//方法2:从头开始遍历
//iter = ve.begin();
}
}
如果想不跳过,也不从头开始,可以不在for中写++iter,而是在for大括号中写++iter,防止跳过删除元素后面的那个元素。
在Linux下的vector erase
同样的代码,发现有些不同,在windows下的野指针居然能通过,郁闷
std::vector<int> ve = {1, 2, 3, 4, 5};
for(auto iter = ve.begin(); iter != ve.end(); ++iter)
{
if(*iter == 3)
{
auto i = ve.erase(iter); //居然可以成功
std::cout << "*i: " << *i << std::endl; //*i: 4
}
}
网友评论