Я пытаюсь перебрать список, а затем, если номер пластины объекта соответствует номеру, указанному в параметрах, и если сбор (рассчитанный в 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;
}
Я предполагаю, что это не ошибка компиляции, а скорее утверждение, которое сработало. У вас есть ошибка!
Допустим, вы на последнем элементе, и все ваши условия применяются. Итак, мы делаем:
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;
});
Итак, как объяснил Барри, проблема, которая вызывала неудачное утверждение, заключалась в том, что итератор будет пытаться 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;
}
}
}