C ++ | Итератор списка не может быть увеличен

Я пытаюсь перебрать список, а затем, если номер пластины объекта соответствует номеру, указанному в параметрах, и если сбор (рассчитанный в toll ()) меньше или равен заданным центам, удалить / удалить объект из списка. Я продолжаю получать сообщение об ошибке, что итератор списка не может быть увеличен, и я не знаю, как это исправить.

void one_time_payment(string& plate_number, int cents) {
// TODO: REWRITE THIS FUNCTION
std::list<LicenseTrip>:: iterator it;
for (it = listLicense.begin(); it != listLicense.end(); std::advance(it, 1)) {
if (it->plate_number().compare(plate_number) == 0) {
cout << "Matching Plate Found" << endl;
if (it->toll() <= cents) {
cout << "Can be paid" << endl;
it = listLicense.erase(it); //Error: list iterator cannot be incremented
}
}
}
cout << "End of Iterator" << endl;
}

0

Решение

Я предполагаю, что это не ошибка компиляции, а скорее утверждение, которое сработало. У вас есть ошибка!

Допустим, вы на последнем элементе, и все ваши условия применяются. Итак, мы делаем:

it = listLicense.erase(it);

Сейчас, it является end(), Но сразу после этого, в конце тела цикла for, мы продвигаемся it! Это неопределенное поведение! Следовательно: итератор списка не может быть увеличен.

Чтобы помочь нам написать это правильно, есть list::remove_if:

listLicense.remove_if([&](const LicenseTrip& trip){
return trip.plate_number() == plate_number &&
trip.toll() <= cents;
});
1

Другие решения

Итак, как объяснил Барри, проблема, которая вызывала неудачное утверждение, заключалась в том, что итератор будет пытаться it за end() который дал бы неопределенное поведение. В моем случае it потребуется только один раз (используется только для поиска LicenseTrip с соответствием plate_number), так что достаточно положить break; после listLicense.erase(it), Окончательный рабочий код выглядит следующим образом:

 void one_time_payment(string& plate_number, int cents) {
std::list<LicenseTrip>:: iterator it;
for (it = listLicense.begin(); (it != listLicense.end()) ; std::advance(it, 1)) {
if (it->plate_number().compare(plate_number) == 0 && it->toll() <= cents)
if (it->toll() <= cents) {
listLicense.erase(it);
break;
}
}
}
-2

По вопросам рекламы [email protected]