Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从事件的迭代列表中删除元素_C++_List - Fatal编程技术网

C++ 从事件的迭代列表中删除元素

C++ 从事件的迭代列表中删除元素,c++,list,C++,List,想知道从事件循环中不断迭代的列表中删除元素的最佳方法是什么。 我有一个更新列表的事件循环 for (auto pIt = this->particles.begin(); pIt != this->particles.end(); pIt++) { (*pIt)->Update(system, gameTime); } 在某个基于事件的时间,我必须从列表中删除一个随机元素。 它在一个单独的函数中处理,使用: this->particles.remove_if([

想知道从事件循环中不断迭代的列表中删除元素的最佳方法是什么。 我有一个更新列表的事件循环

for (auto pIt = this->particles.begin(); pIt != this->particles.end(); pIt++) {
    (*pIt)->Update(system, gameTime);
}
在某个基于事件的时间,我必须从列表中删除一个随机元素。 它在一个单独的函数中处理,使用:

this->particles.remove_if([particle](Particle *ptc)->bool {
    return ptc == particle;
});

这会导致列表迭代运行时错误,因为循环中的迭代器无效。解决这种情况的最佳方法是什么?

擦除函数必须能够访问循环中使用的迭代器(使其成为成员变量),如果迭代器指向要删除的元素,则递增迭代器。这样可以防止循环迭代器因擦除而失效

例如:

#include <iostream>
#include <list>

struct Explosion;

struct Particle {
    void update(Explosion&);
};

struct Explosion {
    std::list<Particle> particles;
    std::list<Particle>::iterator particle_iter;

    void update() {
        for(particle_iter = particles.begin(); particle_iter != particles.end(); ) {
            auto to_call = particle_iter++;
            to_call->update(*this);
        }
    }

    template<class Condition>
    void filter(Condition condition) {
        for(auto i = particles.begin(); i != particles.end();) {
            auto to_remove = i++;
            if(condition(*to_remove)) {
                // Remove the element.
                if(particle_iter == to_remove)
                    particle_iter = i;
                particles.erase(to_remove);
            }
        }
    }
};

void Particle::update(Explosion& explosion) {
    explosion.filter([this](Particle& other) { return this == &other; });
    // The above ends up destroying this object.
    // Cannot no longer access this and should only return.
}

int main() {
    Explosion explosion{{Particle{}, Particle{}}, {}};
    std::cout << explosion.particles.size() << '\n';
    explosion.update();
    std::cout << explosion.particles.size() << '\n';
}
#包括
#包括
结构爆炸;
结构粒子{
无效更新(爆炸&);
};
结构爆炸{
列出粒子;
std::list::iterator particle\u iter;
无效更新(){
对于(particle_iter=particles.begin();particle_iter!=particles.end();){
自动调用=粒子调用++;
调用->更新(*此项);
}
}
模板
空隙过滤器(条件){
对于(自动i=particles.begin();i!=particles.end();){
自动删除=i++;
如果(条件(*删除)){
//拆下该元件。
如果(粒子=移除)
粒子_iter=i;
粒子。擦除(删除);
}
}
}
};
空心粒子::更新(爆炸和爆炸){
explosion.filter([this](粒子和其他){返回this==&other;});
//以上内容最终会破坏此对象。
//无法再访问此文件,只能返回。
}
int main(){
爆炸爆炸{{粒子{},粒子{},{};

std::cout我假设元素的删除发生在
Update()
函数中,“list”实际上是
std::list
而不是
std::vector

不要在循环头中执行
pIt++
。而是在调用
Update()
之前执行
pIt++
。对返回的原始对象调用
Update()

for (auto pIt = this->particles.begin(); pIt != this->particles.end(); ) {
    auto pForCall = *(pIt++);
    pForCall->Update(system, gameTime);
}

另一种不起作用的情况是,被删除的元素不是我们调用的
Update
元素。

这听起来像是从多个线程并发访问?在这种情况下,您需要使用互斥锁来锁定对列表的访问。请提供一个“否”,多个线程之间不存在并发。这是一个single线程应用程序。事件循环在每一帧上运行。在特定条件下,粒子类会触发被删除。因为它已经在事件循环中使用,所以它会崩溃。如果这一切都在一个线程上,那么不清楚迭代器在这段代码中是如何变得无效的,您需要发布一个mcve@AshutoshRautela向量问题巧妙地。列表的一点是,元素可以在内存中的任何位置更新,这意味着cpu在迭代时可能必须访问每个元素的ram。列表的迭代速度通常令人惊讶,而且通常非常慢。@George它可以防止迭代器失效。@user463035818显然。可能对OP;)看起来是个不错的解决方案。但是问题是我还有一个函数render这是一个生命周期挂钩,在更新生命周期挂钩之后调用。void Explosion::render(Graphics*Graphics)const{for(auto-pIt=This->particles.begin();pIt!=This->particles.end();pIt++{pIt-->render(Graphics);}所以我不能使用成员迭代器variables@AshutoshRautela不清楚为什么不能使用成员变量。可能是您想在问题中添加这些详细信息和代码。这会有什么帮助?@ashutshrautela It post递增迭代器,返回迭代器递增之前引用的值。When
Update()
然后被调用,即使它删除了位于原始迭代器位置的元素,当前迭代器也不会失效,因此循环不会出现故障OK。但问题是删除不是通过更新函数发生的。它发生在随机时间间隔事件上。基本上,删除代码位于另一个在事件中调用。@ashutshrautela如果该事件是在
Update()
内部处理的,则此方法可避免
Update()
使循环无效。如果不是,则事件与循环干扰的唯一方式是事件与循环并行运行,在另一个线程或中断中,在这种情况下,您必须同步对列表的访问以避免并发访问。@RemyLebeau您的解决方案肯定解决了删除在更新中的情况,在这种情况下,您将保存当前循环中的迭代器,使其不会失效。我提到的第一个循环是在无限循环中的应用程序中被调用,基本上它是在游戏循环中运行的。粒子以随机间隔死亡,因此死亡粒子在死亡后将从容器中删除。希望我能够更好地解释上下文