vector的erase失效问题
程序员文章站
2022-07-15 09:50:13
...
VS和CGwin的实现效果还不一样,这里先记录下问题及解决方法。欢迎和大家一起探讨。
vector容器erase操作后iterate失效真相
一、VS环境下erase代码分析
代码:
for (auto iter = vec.begin(); iter != vec.end(); ++iter)
{
if (3 == *iter)
{
vec.erase(iter);
}
}
这种写法隐藏一个错误,当erase执行后,弹出错误:
查看源码:
iterator erase(const_iterator _Where)
{ // erase element at where
if (_VICONT(_Where) != &this->_Get_data()
|| _VIPTR(_Where) < this->_Myfirst()
|| this->_Mylast() <= _VIPTR(_Where))
_DEBUG_ERROR("vector erase iterator outside range");
_Move(_VIPTR(_Where) + 1, this->_Mylast(), _VIPTR(_Where));
_Destroy(this->_Mylast() - 1, this->_Mylast());
_Orphan_range(_VIPTR(_Where), this->_Mylast());
--this->_Mylast();
return (_Make_iter(_Where));
}
以及Make_iter:
iterator _Make_iter(const_iterator _Where) const
{ // make iterator from const_iterator
return (iterator(_Where._Ptr, &this->_Get_data()));
}
vector容器erase操作后iterate失效真相 这篇文章中认为erase先移动覆盖,再删除释放,那为什么会crash掉呢,问题就出在了erase的输入上,看到了没有,erase的输入是 (const_iterator _Where),是const_iterator,没错,都是const_iterator惹得祸呀,在return语句中(_Make_iter(_Where))便是将_Where变成了普通的iterator。
二、SGI源码erase代码分析
iterator erase(iterator position) {
if (position + 1 != end())
copy(position + 1, finish, position);
--finish;
destroy(finish);
return position;
}
从上述代码可以看到,返回的postion就是输入的迭代器,上述代码中,并没有发生内存的重新分配,只是将position后面的所有元素向前移动一个位置,再将最后一个元素删除并释放内存,所以,原position的位置并没有发生变化,输入迭代器本身并没有失效。
三、解决方法
从CPP官网可以分析出:
vector中在删除一个元素后,迭代器会自动指向下一个元素,很可能导致迭代器越界。
因此,我们的正确代码是:
//方法1
for (auto iter = vec.begin(); iter != vec.end(); ++iter)
{
if (3 == *iter)
{
iter = vec.erase(iter);
iter--;
}
}
//方法2
for (auto iter = vec.begin(); iter != vec.end();)
{
if (3 == *iter)
{
iter = vec.erase(iter);
}
else
{
iter++;
}
}
推荐阅读
-
解决vuecli3.0热更新失效的问题
-
jquery动态改变onclick属性导致失效的问题解决方法
-
解决Spring国际化文案占位符失效问题的方法
-
Android定时器实现的几种方式整理及removeCallbacks失效问题解决
-
解决layer.open后laydate失效的问题
-
关于扩展 Laravel 默认 Session 中间件导致的 Session 写入失效问题分析
-
解决android Listview的item中最外层Margin失效的问题
-
基于vue打包后字体和图片资源失效问题的解决方法
-
解决v-for中使用v-if或者v-bind:class失效的问题
-
用jquery修复在iframe下的页面锚点失效问题