列出迭代器不可递增的断言

时间:2018-05-21 07:57:23

标签: visual-c++ game-development listiterator const-iterator

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 }

1 个答案:

答案 0 :(得分:0)

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

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

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

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

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

或者您可以将colliders_转换为侵入式列表(例如来自Boost.Intrusive或手写)。侵入性列表非常适合像你这样的情况。