std :: map :: erase & iterators - PullRequest
       5

std :: map :: erase & iterators

1 голос
/ 16 ноября 2011

У меня есть что-то вроде этого кода:

map<int, string> m;

m[1] = "a";
m[2] = "b";
m[3] = "a";
m[4] = "a";
m[5] = "e";
m[6] = "f";
m[7] = "g";
m[8] = "h";
m[9] = "i";

for (it1 = src.begin(); it1 != src.end(); ++it1) {

    for (it2 = it1; it2 != src.end(); ++it2) {
        if (it2 == it1) {
            continue;
        }

        if (it2->second == it1->second) {
            fprintf(stderr, "%u\n", it2->first);
            src.erase(it2);
        }
    }
}

Я использую map, потому что элементы не всегда в этом порядке (1, 2 ...)Итак, вот вопрос

В некоторых случаях значений карты этот код печатает это

2
3
4
6
7
8
9
5

Как это возможно (пропуская 5), если карту сортировать по контейнеру в порядке 1, 2 ... и так далее?

1 Ответ

12 голосов
/ 16 ноября 2011

Ваш erase цикл отключен.Типичная идиома такова:

for(std::map<K,V>::const_iterator it = v.begin(); it != v.end() /* not hoisted! */; /* no increment */ )
{
  // do something
  if (suitable_condition)
  {
    v.erase(it++);
  }
  else
  {
    ++it;
  }
}

Ваш код ошибочно выполняет приращение недопустимого итератора (а именно it2 после erase), что является неопределенным поведением.

(Для некоторых других типов контейнеров erase возвращает итератор для следующего допустимого элемента, поэтому в этих случаях вы должны сказать it = v.erase(it); но детали наилучшего шаблона стирания зависят от конкретного типа контейнера.)

...