简体   繁体   中英

std::map::erase & iterators

I have some thing like this code:

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);
        }
    }
}

I use map , because the elements is not always in this order (1, 2 ...)
So here is the question

In some cases of map values, this code print this

2
3
4
6
7
8
9
5

How it is possible (skipping 5 ), if map sort by container in order 1, 2 ... and so on ?

Your erase loop is off. The typical idiom is this:

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;
  }
}

Your code erroneously performs an increment on an invalid iterator (namely it2 after the erase ), which is undefined behaviour.

(For certain other container types, erase returns an iterator to the next valid element, so in those cases you would say it = v.erase(it) ; but the details of the best erasing pattern depend on the concrete container type.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM