C ++: итератор списка не может быть увеличен - PullRequest
4 голосов
/ 29 мая 2011

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

    for(Drop_List_t::iterator i = Drop_System.begin(); i != Drop_System.end() && !Drop_System_Disable; /**/)
{
    if(Player->BoundingBox.Intersect(&(*i)->BoundingBox))
    {
        i = Drop_System.erase(i);
    }

    ++i; //List iterator crashes here if last entry was deleted
}

Я не могу понять, что я делаю неправильно ... Есть предложения?

Ответы [ 3 ]

14 голосов
/ 29 мая 2011

Ваш алгоритм некорректен, потому что вы не поняли, что вернул erase.

Когда вы используете erase, он удаляет элемент, на который указывает итератор, и возвращает итератор к следующему элементу.

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

Это normal код, который вы должны были получить:

if (Player->BoundingBox.Intersect(i->BoundingBox)) {
  i = Drop_System.erase(i);
}
else {
  ++i; 
}

И это аккуратно решает проблему, с которой вы столкнулись!Потому что когда вы erase последний элемент, erase вернет тот же итератор, что и end, то есть итератор, указывающий элемент «один за последним».Этот итератор не должен никогда увеличиваться (его можно уменьшить, если список не пуст).

5 голосов
/ 29 мая 2011

Вы должны поместить ++i в предложение else. Функция erase возвращает следующий действительный итератор - и вы затем увеличиваете его, гарантируя, что вы не выполняете итерацию по каждому элементу. Вы должны увеличивать его только в том случае, если вы решили не стирать.

4 голосов
/ 29 мая 2011

Вы хотите:

if(Player->BoundingBox.Intersect(&(*i)->BoundingBox))
{
    i = Drop_System.erase(i);
}
else {
    ++i; 
}
...