您的位置:首页 > 其它

从stl中容器中删除元素

2012-04-11 18:38 176 查看
使用STL的几个容器,经常会遇到遍历所有元素,然后删除满足某些条件的元素。直接删除是会有问题的,比如:

for (vector<T>::iterator it = lst.begin(); it != lst.end(); ++it)
{
if(condition)

{
lst.erase(it);
}

}


因为对list而言,一旦一个元素被删除了,指向该节点的iterator可能会失效,再执行++it可能就会有问题。

查了一下stl的源码,list的源码在:stl_list.h

iterator erase(iterator __position);


具体的实现在:list.tcc

template<typename _Tp, typename _Alloc>
typename list<_Tp, _Alloc>::iterator
list<_Tp, _Alloc>::
erase(iterator __position)
{
  iterator __ret = iterator(__position._M_node->_M_next);
  _M_erase(__position);
  return __ret;
}


可以看到,在list的实现里,先用__ret指向了下一个节点,然后返回这个值,因此上面的代码这样写就没问题了:

for (vector<T>::iterator it = lst.begin(); it != lst.end();)
{
if(condition)
{
it = lst.erase(it);
}
else
{
++it;
}
}


对与vector实现也是一样的,只是vector是类数组的实现,把后面的元素拷贝到当前位置来。

vector.tcc

template<typename _Tp, typename _Alloc>
typename vector<_Tp, _Alloc>::iterator
vector<_Tp, _Alloc>::
erase(iterator __position)
{
if (__position + 1 != end())
std::copy(__position + 1, end(), __position);
--this->_M_impl._M_finish;
this->_M_impl.destroy(this->_M_impl._M_finish);
return __position;
}


这是对于linux自带的stl源码,不知对于其它的stl版本是否也是这样。在http://www.cplusplus.com上查看了一下关于list和vector erase函数的说明:

在list::erase中:
Return value
A bidirectional iterator pointing to the new location of the element that followed the last element erased by the function call, which is the list end if the operation erased the last element in the sequence.


这表示这样使用是安全的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: