列表迭代器不可递增断言



DoCollision函数是一个回调函数,它通过迭代碰撞器列表来检查每一帧的冲突。

void Collision::DoCollisions(Game *game){
for (ColliderList::const_iterator colliderAIt = colliders_.begin();
colliderAIt != colliders_.end();
colliderAIt++)
{
ColliderList::const_iterator colliderBIt = colliderAIt;
for (++colliderBIt; colliderBIt != colliders_.end(); ++colliderBIt)
{
Collider *colliderA = *colliderAIt;
Collider *colliderB = *colliderBIt;
if (CollisionTest(colliderA, colliderB))
{
game->DoCollision(colliderA->entity, colliderB->entity);
}
}
}

如果任何两个游戏实体的碰撞测试通过,则游戏实体(所有游戏对象的基类(类析构函数调用函数 DestroyCollider,该函数从列表中删除相应的碰撞体元素。

void Collision::DestroyCollider(Collider *collider){
colliders_.remove_if(std::bind1st((std::equal_to<Collider *>()), collider));
delete collider }

您正在删除迭代器指向的列表元素。这使迭代器无效,这意味着您不能再使用它。

列表或向量的典型删除循环如下所示:

for (auto iterator = list.begin(); iterator != list.end(); ) {
if (should_remove(iterator)) {
iterator = list.erase(iterator);
} else {
++iterator;
}
}

请注意,如果要删除元素,迭代器不会递增,而是替换为erase调用的结果。

您必须找到一种方法来重构代码以匹配此模式。这很复杂,因为您的条件在碰撞函数中很深,但您可以这样做(顺便说一下,这样做的好处是通过摆脱线性搜索来提高代码的效率(,或者您可以,而不是立即删除元素,将它们收集到单独的列表中,然后在完成对主列表的迭代后删除它们。

或者你可以把colliders_变成一个侵入性列表(例如,从Boost.Intrusive,或手写(。侵入性列表非常适合像您这样的情况。

最新更新