从 C++ std::vector 中删除元素

Posted

技术标签:

【中文标题】从 C++ std::vector 中删除元素【英文标题】:Removing elements from C++ std::vector 【发布时间】:2010-04-15 03:17:04 【问题描述】:

在遍历 C++ 向量时,从 C++ 向量中删除元素的正确方法是什么?我正在迭代一个数组并想要删除一些符合特定条件的元素。有人告诉我,在遍历期间修改它是一件坏事。

我想我还应该提到这是一个指针数组,我需要在删除它们之前释放它们。

编辑:

所以这是我的代码的 sn-p。


void RoutingProtocolImpl::removeAllInfinity()

  dv.erase(std::remove_if(dv.begin(), dv.end(), hasInfCost), dv.end()); 


bool RoutingProtocolImpl::hasInfCost(RoutingProtocolImpl::dv_entry *entry)

  if (entry->link_cost == INFINITY_COST)
  
    free(entry);
    return true;
  
  else
  
    return false;
  


编译时出现以下错误:


RoutingProtocolImpl.cc:368: error: argument of type bool (RoutingProtocolImpl::)(RoutingProtocolImpl::dv_entry*)' does not matchbool (RoutingProtocolImpl::)(RoutingProtocolImpl::dv_entry)'

对不起,我是一个 C++ 新手。

【问题讨论】:

不应该使用delete 而不是free 吗? free 是一种 C 机制,不应与 Object 代码混淆。 此外,如果您有vector<T*> 并且vector 拥有对象的所有权,请考虑改用boost::ptr_vector<T>,这样您就可以确保不会泄漏;) 接口非常相似到vector<T>,它只是提供对指针和所有权的处理。 @garsh0p:这和你之前的问题 (***.com/questions/2642671/…) 几乎相同(看起来是复制和粘贴的)。请不要那样做。如果您想为某个问题添加更多详细信息,请编辑您现有的问题,或者只是为您的问题添加评论。 @Evan Teran:下面的 Brian R. Bondy 告诉我要创建一个新问题... 【参考方案1】:

vector 的erase() 方法返回一个新的迭代器,可以用来继续迭代:

std::vecor<MyClass> v = ...;
std::vecor<MyClass>::iterator it = v.begin();
while (it != v.end()) 
  if (some_condition(*it)) 
    it->cleanup(); // or something
    it = v.erase(it);
  
  else 
    ++it;
  

【讨论】:

+1 用于实际回答问题,而不是描述完全不同的方法。这个问题具体说在遍历它时 注意:一定要记得将it分配给erase返回的迭代器!很容易错过,没有它,代码仍然看起来没问题,但它会死得很惨。 +1 的原因与 kibibu 相同,但人们应该更喜欢算法调用而不是显式循环。【参考方案2】:
bool IsEven (int i) 
 
  return (i%2) == 0; 


//...

std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.erase(std::remove_if(v.begin(),v.end(),IsEven), v.end()); 
//v now contains 1 and 3

【讨论】:

如果我的向量包含需要在删除后释放的指针,我该怎么做? @user219847 您可以将指针包装在 Boost:smart_ptr 对象中。 @wheaties:同意在使用 STL 容器时使用智能指针更简洁。 在示例中,谓词 IsEven 可以处理释放指向的内存...这是对您正在开发的应用程序最有意义的问题...我倾向于更喜欢 for_each因为它更具可读性——对我来说。 @user219847:你可以按照wheaties所说的去做,你可以使用boost的ptr_container库,或者你可以使用std::partition(见我的回答)【参考方案3】:

与 Brian R. Bondy 的回答相同,但我会使用仿函数而不是函数 指针,因为编译器更擅长内联它们:

struct IsEven : public std::unary_function<int, bool>

    bool operator()(int i) 
     
      return (i%2) == 0; 
    ;


//...

std::erase(std::remove_if(v.begin(),v.end(),IsEven()), v.end());

编辑:回应 如果我的向量包含在删除后需要释放的指针,我该怎么做?

struct IsEven : public std::unary_function<int, bool>

    bool operator()(int i) 
     
      return (i%2) == 0; 
    ;


struct DeletePointer : public std::unary_function<myPointedType *, void>

    void operator()(myPointedType * toDelete)
    
        delete toDelete;
    ;


//...

typedef std::vector<something>::iterator Iterator_T;
Iterator_t splitPoint = std::partition(v.begin(),v.end(),IsEven());
std::for_each(v.begin(), splitPoint, DeletePointer());
v.erase(v.begin(), splitPoint);

【讨论】:

以上是关于从 C++ std::vector 中删除元素的主要内容,如果未能解决你的问题,请参考以下文章

从 std::vector 中删除多个对象?

是否有一个函数可以从向量中删除一个元素而不在 c++ stdlib 中移动它?

使用模板时如何从 std::vector 中删除元素?

有没有更好的替代 std::remove_if 从向量中删除元素的方法?

为啥从 std::vector 中随机删除比 std::list 快?

为啥 vector::clear 不从向量中删除元素?