стереть в std :: vector, отладка, выпуск - PullRequest
0 голосов
/ 06 декабря 2011

std::vector<int> va; // и push_back 1 ~ 100

std::vector<int>::iterator i = va.begin();
for(i; i != va.end(); )
{
    if((*i) == 5) va.erase(i);
    else i++
}

Этот код на 100% не работает при отладке.

Но не прерывайте этот код при запуске.

Почему это случилось?

Чем отличается режим отладки и выпуска в этом коде?

Ответы [ 3 ]

2 голосов
/ 06 декабря 2011

У вас неопределенное поведение, потому что вы используете недопустимый итератор (i признан недействительным erase()).

Избегайте всей проблемы, используя Erase-remove Idiom :

va.erase(std::remove(va.begin(), va.end(), 5), va.end());
1 голос
/ 06 декабря 2011

Как уже отмечали другие, сбой происходит из-за недействительного итератора, который вы продолжаете использовать после вызова va.erase().

Теперь о том, почему он работает в режиме Release, заключается в том, что в некоторых случаях итератор для std::vector<> в режиме Release является простым указателем на динамически размещенный массив. Когда вы вызываете стирание, итератор продолжает указывать на тот же элемент массива, в то время как содержимое массива было перемещено функцией erase. Это неопределенное поведение и специфическая реализация стандартной библиотеки, но очень распространенное. Ни при каких обстоятельствах не следует полагаться на поведение переносимого кода.

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

1 голос
/ 06 декабря 2011

vector::erase возвращает новый итератор, поскольку он делает текущий недействительным.

if((*i) == 5) va.erase(i);

должно быть

if((*i) == 5) i = va.erase(i);
...