迭代的正确方法是使用迭代器。但是,我认为通过擦除,迭代器是无效的。
基本上我想做的是:
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(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());
注意在Boost和C++ 11中都存在lambda来简化此过程。
关于c++ - 从std::vector删除同时为每个?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3938838/