擦除从一个std ::向量,而为每个?
迭代的正确方法是使用迭代器。 但是,我认为通过擦除,迭代器是无效的。
基本上我想要做的是:
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()); }
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(N 2 )(每个元素都被擦除并移动)到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中。