Векторный итератор в ошибке итератора

Работаю над игрой с астероидом для своего портфолио. Игра обнаружила ошибку со следующим блоком кода. Ошибка просто в том, что итератор не может быть удален, но я сузил ошибку. Я расскажу об этом после того, как покажу вам код:

void Game::Update()
{
if (elapsedTime > REFRESH_RATE)
{
    player->Update(elapsedTime);

    std::vector<Asteroid*>::iterator iterator= bigAsteroids.begin();
    std::vector<Bullet*>::iterator iter = bullets.begin();

    // *********************** //
    while (iterator!= bigAsteroids.end())
    {
        if (*iterator != nullptr) // Checks to see if player is colliding with an asteroid and updates the asteroid
        {
            player->CheckCollisionsAsteroid( *iterator );

            // *********************** // Checks to see if bullet is colliding with asteroid 
            while (iter != bullets.end())
            {
                if (*iter != nullptr)
                {
                    if ((*iter)->CheckCollisionsAsteroid( **iterator ))
                    {
                        size_t i = iterator - bigAsteroids.begin();
                        iter = bullets.erase(iter);
                        iterator = bigAsteroids.erase(iterator);
                        printf("\nAsteroid destroyed at position %i", i);
                    }
                    else
                    {
                        ++iter;
                    }
                }
            }
            iter = bullets.begin(); // Reset the bullet iterator else we'd only get to check 1 asteroid

            // *********************** //
            if (*iterator != nullptr && iterator != bigAsteroids.end()) { (*iterator)->Update(elapsedTime); }
        }
        if (*iterator != nullptr && (iterator!= bigAsteroids.end()))
        {++iterator;}
    }
    // *********************** //
    Clock.Reset(); 
}
}

Если все выглядит немного запутанным, вот краткое объяснение:

Когда итератор проходит через каждый из астероидов, я проверяю, сталкивается ли игрок с каждым из астероидов. В настоящее время это ничего не делает

Затем я перебираю свой вектор пуль, сравнивая каждую пулю с текущим астероидом. если происходит столкновение, я уничтожаю, стираю как пулю, так и астероид, и распечатываю, какую позицию занимал разрушенный астероид в векторе.

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

Моя основная проблема в настоящее время - это вызов Update астероидом (* iterator) ‹.

Проблема возникает только тогда, когда я стираю последний объект в векторе астероидов. Я знаю, что стирание возвращает итератор к следующему объекту - если следующий объект не существует, будет выдана ошибка (поскольку итератор затем указывает на nullptr, правильно?). Я безрезультатно проверяю nullptr ..

Есть ли у кого-нибудь совет или помощь, которые они могут предложить? Был бы очень признателен, почесал бы голову в течение нескольких часов!


person DerryHolt    schedule 22.02.2013    source источник
comment
Если бы вы назвали свои итераторы в честь того, на что они ссылаются, например, itAsteroid и itBullet.   -  person Angew is no longer proud of SO    schedule 22.02.2013
comment
@Angew Я часто это понимаю, ха-ха, я продолжаю переписывать код, поэтому сейчас набираю bulletIter или asteroidIter вместо iter или iterator ..: P В финальной версии они будут реализованы, спасибо. И Боб Хммм .. Я вернусь к вам, спасибо за помощь   -  person DerryHolt    schedule 22.02.2013


Ответы (1)


Проблема в том, что когда вы уничтожите последний астероид, iterator будет установлено в bigAsteroids.end() (присвоено результату erase()). Затем после завершения внутреннего цикла while выполняется разыменование iterator. Итератор, прошедший через конец, не может быть разыменован.

Вам нужно будет изменить порядок проверок:

if (iterator != bigAsteroids.end() && *iterator != nullptr)
person Angew is no longer proud of SO    schedule 22.02.2013
comment
Это не столько последний астероид. Это может быть первый астероид, который я сниму. Если это ПОСЛЕДНИЙ астероид в векторе (как в конце), то возникает ошибка. Не думаю, что мне удалось спуститься ни на один астероид, чтобы выстрелить! Ха-ха - person DerryHolt; 22.02.2013
comment
Он означает: когда вы вызываете bigAsteroids.erase(iterator), iterator устанавливается в bigAsteroids.end(). *iterator != nullptr завершится ошибкой, а iterator != bigAsteroids.end() вернет false, поэтому измените порядок условий, и все будет в порядке - person marsze; 22.02.2013
comment
Оххххххх. Я понимаю. Я все изменил: if (itAsteroid != bigAsteroids.end()) { (*itAsteroid)->Update(elapsedTime); } И это все равно вызывало ошибки. НО, затем я изменил строку ниже: if ( itAsteroid!= bigAsteroids.end() && *itAsteroid != nullptr ) {++itAsteroid;} И он сделал, как вы сказали. Что я с вами сделал, ребята: P Спасибо вам обоим! - person DerryHolt; 22.02.2013