Ответ 1
После некоторого использования этой идиомы, я думаю, что изменение в цикле в ответе Jarod42 заключается в том, чтобы сделать вещи более безопасными и поддерживать типичные тонкости цикла for(;;)
:
for (auto it = testcont.rbegin(), nit = it; it != testcont.rend(); it = nit) {
nit = next(it);
// whatever... maybe a continue somewhere or maybe not
if (WE_WANT_TO_ERASE(it)) {
nit = decltype(it){ testcont.erase(std::next(it).base()) };
}
// whatever... maybe a continue somewhere or maybe not
}
Использование цикла в другом ответе слишком опасно. Если бы кто-то бездумно добавил a continue;
где-то в цикле, не увеличивая сначала итератор, результатом будет бесконечный цикл. Поскольку, вначале, это может выглядеть как обычный цикл for(;;)
, я считаю, что это рано или поздно произойдет. Аналогичным образом, если в цикле есть ветки, и если одна из этих ветвей пренебрегает увеличением итератора, вводится другая ошибка. Наконец, если вы выполните erase()
, вы должны быть уверены в continue
, прежде чем увеличивать итератор, иначе у вас будет еще одна ошибка.
Используя модифицированный цикл выше, цикл можно обрабатывать так же, как обычный цикл for(;;)
. Трюк состоит в том, чтобы увеличить nit
( "следующий итератор" ) как первую строку тела цикла. Тогда вам не нужно беспокоиться. Единственный раз, когда вам нужно обновить nit
, вы делаете erase()
. Все остальное работает так, как можно было бы ожидать, что цикл for будет работать.
Последнее замечание: я первоначально задал вопрос о картах, но это будет корректно работать и для vector
, list
и т.д.