// 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;
}
为什么这会产生类似
的输出a => 10
b => 20
c => 30
d => 40
e => 50
f => 60
不应该{@ 1}}被删除,但如果我在for循环中声明"a => 10"
,一切都很完美。为什么呢?
答案 0 :(得分:39)
擦除map
的元素会使指向该元素的迭代器无效(在删除所有元素之后)。你不应该重用那个迭代器。
由于C ++ 11 erase()
返回一个指向下一个元素的新迭代器,可用于继续迭代:
it = mymap.begin();
while (it != mymap.end()) {
if (something)
it = mymap.erase(it);
else
it++;
}
在C ++ 11之前,您必须在删除之前手动将迭代器推进到下一个元素,例如:
mymap.erase(it++);
这是有效的,因为it++
的后增量副作用发生在erase()
删除元素之前。由于这可能不是很明显,因此上面的C ++ 11变体应该是首选。
答案 1 :(得分:3)
调用erase()
使迭代器无效。在这种情况下,正在发生的是迭代器指向内存中留下的剩余值(但不依赖于这种未定义的行为!)。在循环之前使用it=mymap.begin()
重置迭代器以获得所需结果。
This answer显示了在迭代std::map
时如何擦除元素:
for(map<T, S*>::iterator it = T2pS.begin(); it != T2pS.end(); T2pS.erase(it++)) {
// wilhelmtell in the comments is right: no need to check for NULL.
// delete of a NULL pointer is a no-op.
if(it->second != NULL) {
delete it->second;
it->second = NULL;
}
}
答案 2 :(得分:1)
这与map
的实施方式有关。让我们说它是某种树,比如:
class map_node {
char key;
int value;
map_node* next;
...
};
当你erase()
迭代器时,你从树中删除节点并释放它的空间。但是直到该内存位置被覆盖,节点的内容仍然在内存中。这就是为什么你不仅可以获得值,还可以获得树中的下一个元素。因此,您的结果是完全可以预期的。
答案 3 :(得分:0)
it
之后 mymap.erase(it)
不再有效。这意味着,它可以做任何想做的事。
答案 4 :(得分:0)
“它”仍然指向同一个位置,擦除不会自动更新迭代器,你必须通过重置迭代器来完成它。实际上,“它”指向已从矢量中删除但仍包含旧数据的旧位置。