use*_*240 2 c++ iterator vector
我做了一个游戏,rambo射击子弹和子弹击中了僵尸,我想从僵尸矢量中删除被击中的僵尸.
这个嵌套循环逐个检查每个僵尸和子弹之间的冲突.它有效一段时间,但当我开始杀死更多时,它会崩溃,因为它想要使用已删除僵尸的功能.
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我现在更好地添加it--;了zombies.erase(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()
);
Run Code Online (Sandbox Code Playgroud)
注意:是的,您可以就地使用lambda,但我更喜欢命名它们来表明它们的作用.
注意:这使用C++ 11,但是用谓词替换lambda是微不足道的,并且any_of很容易生成,就像all_of和none_of.