调用erase()后std :: map :: iterator出现问题

0x0*_*0x0 18 c++ iterator

// erasing from map
#include <iostream>
#include <map>
using namespace std;

int main ()
{
  map<char,int> mymap;
  map<char,int>::iterator it(mymap.begin());

  // insert some values:
  mymap['a']=10;
  mymap['b']=20;
  mymap['c']=30;
  mymap['d']=40;
  mymap['e']=50;
  mymap['f']=60;

  it=mymap.find('a');
  mymap.erase (it);                   // erasing by iterator

  // show content:
  for (; it != mymap.end(); it++ )
    cout << (*it).first << " => " << (*it).second << endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

为什么这会产生类似的输出

a => 10
b => 20
c => 30
d => 40
e => 50
f => 60
Run Code Online (Sandbox Code Playgroud)

"a => 10"应该删除,但如果我it = mymap.begin()在for循环中声明,一切都很完美.为什么?

程序改编自:http://www.cplusplus.com/reference/stl/map/erase/

sth*_*sth 42

擦除map指向该元素的无效迭代器的元素(在删除所有元素之后).您不应该重用该迭代器.

由于C++ 11 erase()返回一个指向下一个元素的新迭代器,可以用来继续迭代:

it = mymap.begin();
while (it != mymap.end()) {
   if (something)
      it = mymap.erase(it);
   else
      it++;
}
Run Code Online (Sandbox Code Playgroud)

在C++ 11之前,您必须在删除之前手动将迭代器推进到下一个元素,例如:

mymap.erase(it++);
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为it++erase()删除元素之前发生了后增量副作用.由于这可能不是很明显,因此上面的C++ 11变体应该是首选.

  • 我对句子感到困惑.你说"你不应该重用那个迭代器(_OK_),或者在删除发生之前将迭代器推进到下一个元素(_pre-increment_),例如像这样"然后提出一个后增量的例子,然后是重复作为良好代码的一个例子.我希望在这句话之后有一个坏代码的例子. (2认同)