Список итератор не инкрементное утверждение - PullRequest
0 голосов
/ 21 мая 2018

Функция 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 голосов
/ 21 мая 2018

Вы удаляете элемент списка, на который указывает итератор.Это делает недействительным итератор, что означает, что вы больше не можете его использовать.

Типичный цикл удаления для списка или вектора выглядит следующим образом:

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

Обратите внимание, что если элементдолжен быть удален, итератор не увеличен, но вместо этого заменен результатом вызова erase.

Вам нужно будет найти способ реорганизовать свой код, чтобы соответствовать этомушаблон.Это сложно, потому что ваше условие находится глубоко внутри функции столкновения, но вы можете сделать это (что имеет преимущество в том, чтобы сделать ваш код более эффективным, между прочим, избавившись от линейного поиска), или вы можете вместо немедленногоудалив элементы, соберите их в отдельный список, а затем удалите их после завершения итерации по основному списку.

Или вы можете превратить colliders_ в навязчивый список (например, из Boost.Intrusive,или рукописный).Навязчивые списки очень хороши для таких ситуаций, как ваша.

...