在为每个执行 a 时从 std::vector 中擦除?

Erasing from a std::vector while doing a for each?(在为每个执行 a 时从 std::vector 中擦除?)
本文介绍了在为每个执行 a 时从 std::vector 中擦除?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

限时送ChatGPT账号..

迭代的正确方法是使用迭代器.但是,我认为通过擦除,迭代器无效.

The proper way to iterate is to use iterators. However, I think by erasing, the iterator is invalidated.

基本上我想做的是:

for(iterator it = begin; it != end; ++it)
{
    if(it->somecondition() )
    {
     erase it
    }

}

如果没有 v[i] 方法,我怎么能做到这一点?

How could I do this without v[i] method?

谢谢

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() 返回一个新的迭代器:

erase() returns a new iterator:

for(iterator it = begin; it != end(container) /* !!! */;)
{
    if (it->somecondition())
    {
        it = vec.erase(it);  // Returns the new iterator to continue from.
    }
    else
    {
        ++it;
    }
}

请注意,我们不能再将它与预先计算的结束进行比较,因为我们可能会删除它并因此使其无效.我们每次都必须明确地结束.

Note that we can no longer compare it against a precalculated end, because we may erase it and therefore invalidate it. We must get the end explicitly each time.

更好的方法可能是结合 std::remove_iferase().你从 O(N2)(每个元素都会被擦除并随着你的移动而移动)变成 O(N):

A better method might be to combine std::remove_if and erase(). You change from being O(N2) (every element gets erased and shifted as you go) to O(N):

iterator it = std::remove_if(begin, end, pred);
vec.erase(it, vec.end());

其中 pred 是您的移除谓词,例如:

Where pred is your removal predicate, such as:

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());

在你的情况下,你可以让它变得非常通用:

In your case, you can make it pretty general:

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 中都是如此.

Note lambda's exist to simplify this process, both in Boost and C++11.

这篇关于在为每个执行 a 时从 std::vector 中擦除?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

相关文档推荐

OpenGL transforming objects with multiple rotations of Different axis(OpenGL 变换不同轴多次旋转的对象)
GLFW first responder error(GLFW 第一响应者错误)
SOIL not linking correctly(SOIL 连接不正确)
Core profile vs version string? Only getting GLSL 1.3/OGL 3.0 in mesa 10.0.1(核心配置文件与版本字符串?在 mesa 10.0.1 中只获得 GLSL 1.3/OGL 3.0)
What is the range of OpenGL texture ID?(OpenGL 纹理 ID 的范围是多少?)
How taxing are OpenGL glDrawElements() calls compared to basic logic code?(与基本逻辑代码相比,OpenGL glDrawElements() 调用的繁重程度如何?)