我怎样才能删除迭代器的std :: map的元素?
我想通过一个std::map
循环,并根据其内容删除项目。 这个怎么做最好?
如果你有一个C ++ 11兼容的编译器,这是一个简单的方法:
std::map<K, V>::iterator itr = myMap.begin(); while (itr != myMap.end()) { if (ShouldDelete(*itr)) { itr = myMap.erase(itr); } else { ++itr; } }
这个想法是将迭代器从容器的开始处移动到结束处,在每个步骤检查当前的键/值对是否应该被删除。 如果是这样,我们使用erase
成员函数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; } }
这个过程是必需的,因为如果你只是在迭代器上调用erase
,你会使它无效 ,这意味着像增量和减量的操作会导致未定义的行为。 上面的代码通过设置迭代器的副本,推进itr
以便它在下一个元素,然后擦除迭代器的临时副本来解决这个问题。
使用一些聪明的诡计,可以缩小代码的代价是可读性。 以下模式在较早的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; } }
这里使用后增加运算符是一种巧妙的方法,可以复制旧的迭代器(请记住,后缀++运算符返回原始迭代器值的副本),同时也推进旧的迭代器。
这是一个简单的方法:
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; } }
for(MyMap::iterator it = mymap.begin(); it!=mymap.end(); ) { if(mycondition(it)) it = mymap.erase(it); else it++; }
编辑:似乎这只适用于MSVC
edit2:在c ++ 0x这也适用于关联容器