从 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 match
bool (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 中删除元素的主要内容,如果未能解决你的问题,请参考以下文章
是否有一个函数可以从向量中删除一个元素而不在 c++ stdlib 中移动它?
有没有更好的替代 std::remove_if 从向量中删除元素的方法?