Векторный итератор не инкрементный .erase()

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

for (std::vector<Coin>::iterator i=CoinSet.begin(); i!=CoinSet.end(); i++) 
{
    if (i->PlayerClear(player.collider()) == true)
    {
        score++;
        cout<<score<<endl;
        CoinSet.erase(i);
    }
}

Этот код отлично работает до "CoinSet.erase(i)", я пробовал использовать "CoinSet.clear()" в разных точках, но безрезультатно. Любая помощь в этом будет здорово, заранее спасибо!


person user3027864    schedule 27.04.2014    source источник


Ответы (2)


Это обсуждалось до смерти. Вы не должны работать с недопустимым итератором. Вы хотите что-то вроде этого:

for (auto it = CoinSet.begin(); it != CoinSet.end(); /* no increment here! */ )
{
    if (/* ... */)
    {
        // ...
        CoinSet.erase(it++);
    }
    else
    {
        ++it;
    }
}
person Kerrek SB    schedule 27.04.2014
comment
Большое спасибо, я потратил хороший час на изучение перед публикацией, но не нашел слишком много актуального (я совсем новичок). В любом случае, теперь я получаю несовместимые итераторы векторов ошибок? - person user3027864; 28.04.2014
comment
@ user3027864: Если ваш компилятор не поддерживает C++11, вы не можете использовать auto таким образом, поэтому продолжайте указывать тип. - person Kerrek SB; 28.04.2014
comment
@Veritas: Что, если it == begin()?! - person Kerrek SB; 28.04.2014
comment
Хорошо, заработало, большое спасибо! Довольно раздражает, что я могу потратить так много времени на одну деталь, а кто-то другой починит ее за 5 минут. Но практика делает совершенным! - person user3027864; 28.04.2014
comment
@user3027864: Нет. Учиться на своих ошибках — значит совершенствоваться. Урок сегодня состоит в том, чтобы использовать отладчик. Будьте систематичны, будьте методичны. Не программируйте путем случайного угадывания. У меня была точно такая же проблема, когда я был маленьким и впервые использовал erase, и хотя документация действительно говорит вам, что erase делает итератор недействительным, большинство из нас не обращает внимания на эти вещи (не говоря уже о чтении), поэтому мы нужно узнать трудный путь. Отладчик сообщает вам, что пошло не так, а тогда вы сгораете и обращаете внимание на документацию. Этот процесс работает очень хорошо. - person Kerrek SB; 28.04.2014

Мне не нравится помещать ++-операторы в аргумент. Следовательно, erase() возвращает итератор, указывающий на следующий элемент, поэтому строку стирания можно заменить на:

it = CoinSet.erase(it); // iterator is replaced with valid one
person Ozzy    schedule 05.07.2018