在为每个执行一次时从 std::vector 中擦除?
Posted
技术标签:
【中文标题】在为每个执行一次时从 std::vector 中擦除?【英文标题】:Erasing from a std::vector while doing a for each? 【发布时间】:2010-10-15 01:30:03 【问题描述】:迭代的正确方法是使用迭代器。但是,我认为通过擦除,迭代器无效。
基本上我想做的是:
for(iterator it = begin; it != end; ++it)
if(it->somecondition() )
erase it
如果没有 v[i] 方法,我怎么能做到这一点?
谢谢
struct RemoveTimedEvent
bool operator()(const AguiTimedEvent& pX, AguiWidgetBase* widget) const
return pX.getCaller() == widget;
;
void AguiWidgetContainer::clearTimedEvents( AguiWidgetBase* widget )
std::vector<AguiTimedEvent>::iterator it = std::remove_if(timedEvents.begin(),
timedEvents.end(), RemoveTimedEvent());
timedEvents.erase(it, timedEvents.end());
【问题讨论】:
【参考方案1】:erase()
返回一个新的迭代器:
for(iterator it = begin; it != end(container) /* !!! */;)
if (it->somecondition())
it = vec.erase(it); // Returns the new iterator to continue from.
else
++it;
请注意,我们不能再将其与预先计算的结束进行比较,因为我们可能会删除它并因此使其无效。我们每次都必须明确地结束。
更好的方法可能是将std::remove_if
和erase()
结合起来。你从 O(N2) (每个元素都会被擦除和移动)变为 O(N):
iterator it = std::remove_if(begin, end, pred);
vec.erase(it, vec.end());
其中pred
是您的删除谓词,例如:
struct predicate // do choose a better name
bool operator()(const T& pX) const // replace T with your type
return pX.shouldIBeRemoved();
;
iterator it = std::remove_if(begin, end, predicate());
vec.erase(it, vec.end());
在你的情况下,你可以让它很笼统:
class remove_by_caller
public:
remove_by_caller(AguiWidgetBase* pWidget) :
mWidget(pWidget)
// if every thing that has getCaller has a base, use that instead
template <typename T> // for now a template
bool operator()(const T& pX) const
return pX.getCaller() == mWidget;
private:
AguiWidgetBase* mWidget;
;
std::vector<AguiTimedEvent>::iterator it =
std::remove_if(timedEvents.begin(), timedEvents.end(), remove_by_caller(widget));
timedEvents.erase(it, timedEvents.end());
注意 lambda 的存在是为了简化这个过程,无论是在 Boost 还是 C++11 中。
【讨论】:
我不确定我是否理解第一种方法是N平方的,为什么不是N,我只迭代一次以删除项目。 当然,除非擦除返回的迭代器将您带回顶部 @Milo:这是 N^2。如果您删除第一个元素,所有其他元素将被复制下来以取而代之。这样做 N 次,你已经触摸了每一个 N^2 次。您可以将参数传递给谓词,谓词会转发它。 第一个 sn-p 可能是错误的,因为end
迭代器在擦除后会失效。
我不会在每次循环迭代时重新评估 end()
,就在调用 erase()
时:for(iterator it = vec.begin(), end = vec.end(); it != end;) ... if (condition) it = vec.erase(it); end = vec.end(); ...
以上是关于在为每个执行一次时从 std::vector 中擦除?的主要内容,如果未能解决你的问题,请参考以下文章
在为 Flutter 编写测试时,当相似的方面出现不止一次时会发生啥?如何筛选出合适的?
AWS.ApiGatewayManagementApi.postToConnection() 调用一次时执行两次