c++ - 在这种情况下如何删除 vector 元素?

标签 c++ vector iterator

我做了一个游戏,兰博射出子弹,子弹击中了僵尸,我想从僵尸 vector 中删除被击中的僵尸。

这个嵌套循环逐一检查每个僵尸和子弹之间的碰撞。它在一段时间内运行良好,但当我开始杀更多的时候,在某个时刻,它崩溃了,因为它想使用一个已清除僵尸的功能。

for ( it = zombies.begin(); it != zombies.end(); ++it ) {
    it->attack();
    for (rambo.it = rambo.bullets.begin(); rambo.it != rambo.bullets.end(); ++rambo.it) {
        if(checkBasicCollision(it,rambo.it) && it != zombies.end()){
            zombies.erase(it);
        }
    }
}

我在 zombies.erase(it); 之后添加了 it--; 现在效果更好,但有时仍然会崩溃。

我认为它的发生就像,例如有 5 个僵尸和 20 颗子弹,僵尸迭代器在第二个僵尸处,第二个僵尸开始子弹循环以检查它是否被击中。循环开始,假设第三颗子弹击中僵尸,但循环仍在继续,即使僵尸被清除,它仍然继续循环。

我添加了中断;在 zombies.erase(it); 之后,现在它没有任何问题。但是代码看起来很脏。有没有另一种方法可以轻松删除当前元素

最佳答案

虽然提出了手动删除的解决方案,但请注意,这不是最惯用的解决方案。在惯用的 C++ 中,您可以像这样在删除-删除习惯用法中使用 std::remove_if 算法:

// 1. A predicate that check whether a zombie was it by any bullet:
auto is_zombie_hit = [&rambo](Zombie const& zombie) {
    auto is_bullet_hitting_zombie = [&zombie](Bullet const& bullet) {
        return checkBasicCollision(zombie, bullet);
    };

    return std::any_of(
        rambo.bullets.begin(),
        rambo.bullets.end(),
        is_bullet_hitting_zombie
    );
};

// 2. Use the erase-remove idiom:
zombies.erase(
    std::remove_if(zombies.begin(), zombies.end(), is_zombie_hit),
    zombies.end()
);

注意:是的,您可以就地使用 lambda,但我更喜欢命名它们以表明它们的作用。

注意:这使用 C++11,但是用谓词替换 lambda 很简单,any_of 的实现很容易生成,很像 all_ofnone_of

关于c++ - 在这种情况下如何删除 vector 元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24852495/

相关文章:

c++ - 我需要我的 vector 的最大大小(我给的值)C++

java - 遍历/更新 HashMap

c++ - 编译器优化打破了惰性迭代器

java - 使用迭代器和 ArrayList 的具有 10 个记录的多个 ArrayList

c++ - CreateIoCompletionPort 的并发线程数

c++ - 用不同的值填充数组/vector 的边缘和中心

c++ - vector 和原始类型初始化

c++ - 如何在 C++ 中过滤字符串 vector ?

c++ - 在一个解决方案中只批量编译一个项目

c++ - QPainter 绘制线条方法