tem*_*def 101
如果你有一个符合C++ 11的编译器,这里有一个简单的方法:
std::map<K, V>::iterator itr = myMap.begin();
while (itr != myMap.end()) {
if (ShouldDelete(*itr)) {
itr = myMap.erase(itr);
} else {
++itr;
}
}
Run Code Online (Sandbox Code Playgroud)
我们的想法是将迭代器从容器的开头向前移动到最后,检查每一步是否应删除当前的键/值对.如果是这样,我们使用erase成员函数删除迭代的元素,然后成员函数将迭代器返回到地图中的下一个元素.否则,我们正常向前推进迭代器.
如果您没有符合C++ 11标准的编译器,或者您正在使用较旧的代码库,那么事情就会有点棘手.在C++ 11之前,erase成员函数不会将迭代器返回到映射中的下一个元素.这意味着为了在迭代时删除元素,您需要使用三部分的舞蹈:
erase旧迭代器的副本.这显示在这里:
std::map<K, V>::iterator itr = myMap.begin();
while (itr != myMap.end()) {
if (ShouldDelete(*itr)) {
std::map<K, V>::iterator toErase = itr;
++itr;
myMap.erase(toErase);
} else {
++itr;
}
}
Run Code Online (Sandbox Code Playgroud)
这个过程是必需的,因为如果你刚刚调用erase了迭代器,你就会使它失效,这意味着增量和减量等操作会导致未定义的行为.上面的代码通过设置迭代器的副本,推进来解决这个itr以便它的下一个单元,然后擦除迭代器的临时副本.
使用一些Clever Trickiness,可以以牺牲可读性为代价缩小代码.以下模式在较旧的C++代码中很常见,但在C++ 11中不是必需的:
std::map<K, V>::iterator itr = myMap.begin();
while (itr != myMap.end()) {
if (ShouldDelete(*itr)) {
myMap.erase(itr++); // <--- Note the post-increment!
} else {
++itr;
}
}
Run Code Online (Sandbox Code Playgroud)
这里使用后增量运算符是一种巧妙的方法来制作旧迭代器的副本(记住postfix ++运算符返回原始迭代器值的副本),同时也推进旧的迭代器.
for(MyMap::iterator it = mymap.begin(); it!=mymap.end(); ) {
if(mycondition(it))
it = mymap.erase(it);
else
it++;
}
Run Code Online (Sandbox Code Playgroud)
编辑:似乎这只适用于MSVC
edit2:在c ++ 0x中,这也适用于关联容器
这是一个简单的方法:
int value_to_delete( 2 );
for( std::map<int, int>::iterator i = mm.begin(); i != mm.end(); ) {
if( i->second != value_to_delete ) {
mm.erase( i++ ); // advance before iterator become invalid
}
else {
++i;
}
}
Run Code Online (Sandbox Code Playgroud)