Если у вас есть C ++ 11-совместимый компилятор, вот простой способ сделать это:
std::map<K, V>::iterator itr = myMap.begin();
while (itr != myMap.end()) {
if (ShouldDelete(*itr)) {
itr = myMap.erase(itr);
} else {
++itr;
}
}
Идея состоит в том, чтобы пройти итератор вперед от начала контейнера до конца, проверяя на каждом шаге, должна ли текущая пара ключ / значение быть удалена. Если это так, мы удаляем элемент, повторяющийся с помощью функции-члена erase
, которая затем возвращает итератор к следующему элементу на карте. В противном случае мы продвигаем итератор вперед нормально.
Если у вас нет компилятора, совместимого с C ++ 11, или вы работаете со старой кодовой базой, все немного сложнее. До C ++ 11 функция-член erase
не возвращала итератор для следующего элемента в карте. Это означало, что для удаления элемента во время итерации вам нужно использовать танец из трех частей:
- Скопировать текущий итератор.
- Переход текущего итератора к следующему элементу.
- Вызовите
erase
на копии старого итератора.
Это показано здесь:
std::map<K, V>::iterator itr = myMap.begin();
while (itr != myMap.end()) {
if (ShouldDelete(*itr)) {
std::map<K, V>::iterator toErase = itr;
++itr;
myMap.erase(toErase);
} else {
++itr;
}
}
Этот процесс был необходим, потому что если бы вы просто вызвали erase
на итераторе, вы аннулировали бы это, означая, что такие операции, как увеличение и уменьшение, привели бы к неопределенному поведению. Приведенный выше код позволяет обойти эту проблему, настроив копию итератора, добавив itr
, чтобы он находился на следующем элементе, а затем удалив временную копию итератора.
Используя некоторую Умную Уловку, можно уменьшить этот код за счет читабельности. Следующий шаблон распространен в старом коде C ++, но не является обязательным в C ++ 11:
std::map<K, V>::iterator itr = myMap.begin();
while (itr != myMap.end()) {
if (ShouldDelete(*itr)) {
myMap.erase(itr++); // <--- Note the post-increment!
} else {
++itr;
}
}
Использование оператора постинкремента здесь - это умный способ сделать копию старого итератора (помните, что оператор postfix ++ возвращает копию исходного значения итератора), одновременно продвигая более старый итератор.