新技能Get!

问题

对于c++里面的容器, 我们可以使用iterator进行方便的遍历. 但是当我们通过iterator对vector/map等进行修改时, 我们就要小心了, 因为操作往往会导致iterator失效, 之后的行为都变得不可预知. 比如:

#include <iostream>
#include <vector> using namespace std; int main()
{
vector<int> a = {12, 23, 34, 45, 56, 67, 78, 89}; for (auto iter = a.begin(); iter != a.end(); ++iter) {
if (*iter > 30) {
a.erase(iter);
}
} for (const auto &element : a) {
cout<<element<<endl;
} return 0;
} 输出: 12
23
45
67
89

cplusplus的reference里对 std::vector::erase 的描述是:

Iterators, pointers and references pointing to position (or first) and beyond are invalidated, with all iterators, pointers and references to elements before position (or first) are guaranteed to keep referring to the same elements they were referring to before the call.

只有删除元素前面的iterator还保持有效, 之后的遍历行为不可预知.

解决方案

对于vector, erase会返回下一个iterator, 因此我们可以使用如下的方法:

#include <iostream>
#include <vector> using namespace std; int main()
{
vector<int> a = {12, 23, 34, 45, 56, 67, 78, 89}; auto iter = a.begin();
while (iter != a.end()) {
if (*iter > 30) {
iter = a.erase(iter);
}
else {
++iter;
}
} for (const auto &element : a) {
cout<<element<<endl;
} return 0;
} 输出: 12
23

  

对于map, 删除iterator只会影响当前的iterator, 因此使用for循环就够了, 比如:

#include <iostream>
#include <map> using namespace std; int main()
{
map<int, int> a = {{1, 12}, {2, 23}, {3, 34}, {4, 45}, {5, 56}, {6, 67}}; for (auto iter = a.begin(); iter != a.end(); ++iter) {
if (iter->second > 30) {
a.erase(iter);
}
} for (const auto &element : a) {
cout<<element.first<<" : "<<element.second<<endl;
} return 0;
} 输出: 1 : 12
2 : 23

  但是更推荐的做法是在erase前让iterator指向下一个元素

#include <iostream>
#include <map> using namespace std; int main()
{
map<int, int> a = {{1, 12}, {2, 23}, {3, 34}, {4, 45}, {5, 56}, {6, 67}}; auto iter = a.begin();
while (iter != a.end()) {
if (iter->second > 30) {
a.erase(iter++);
}
else {
++iter;
}
} for (const auto &element : a) {
cout<<element.first<<" : "<<element.second<<endl;
} return 0;
} 输出: 1 : 12
2 : 23

  

参考资料

http://stackoverflow.com/questions/4645705/vector-erase-iterator

http://stackoverflow.com/questions/4600567/how-can-i-delete-elements-of-a-stdmap-with-an-iterator

c++如何遍历删除map/vector里面的元素的更多相关文章

  1. 【遍历集合】Java遍历List,Map,Vector,Set的几种方法

    关于list,map,set的区别参考http://www.cnblogs.com/qlqwjy/p/7406573.html 1.遍历list @Test public void testList( ...

  2. 删除map、list集合元素总结

    @Testpublic void removeElementFromMap(){Map<Integer, String> test = new HashMap<Integer, St ...

  3. Java 循环遍历删除set list中的元素

    删除List和Set中的某些元素 错误代码的写法: Set<String> set = new HashSet<String>(); set.add("aaaaaa& ...

  4. map/vector遍历删除

    map遍历删除 map<int, vector<int>>::iterator it = g_map.begin(); for (; it != g_map.end(); /* ...

  5. map,vector 等容器内容的循环删除问题(C++)

    map,vector 等容器内容的循环删除问题(C++) map,vector等容器的循环删除不能用普通的方法删除: for(auto p=list.begin();p!=list.end();p++ ...

  6. Set,List,Map,Vector,ArrayList的区别(转)

    JAVA的容器---List,Map,Set Collection ├List │├LinkedList │├ArrayList │└Vector │ └Stack └Set Map ├Hashtab ...

  7. STL容器的遍历删除

    STL容器的遍历删除 今天在对截包程序的HashTable中加入计时机制时,碰到这个问题.对hash_map中的每个项加入时间后,用查询函数遍历hash_map,以删除掉那些在表存留时间比某个阈值长的 ...

  8. STL中用erase()方法遍历删除元素 .xml

    pre{ line-height:1; color:#f0caa6; background-color:#2d161d; font-size:16px;}.sysFunc{color:#e54ae9; ...

  9. STL中用erase()方法遍历删除元素

    STL中的容器按存储方式分为两类,一类是按以数组形式存储的容器(如:vector .deque):另一类是以不连续的节点形式存储的容器(如:list.set.map).在使用erase方法来删除元素时 ...

随机推荐

  1. 编程范式 episode 6 实现stack 栈功能_ to do

    //既然在这里开始,那就在这里结束. 实现stack 功能 ____coding _using subfunction to focus on the main aim of current func ...

  2. (转)iOS sqlite :truncate/delete/drop区分

    转自:http://blog.sina.com.cn/s/blog_6755689f0101fofb.html 相同点: 1.truncate和不带where子句的delete.以及drop都会删除表 ...

  3. Ubuntu中vi常用命令

    在Ubuntu中经常需要修改某些文件,这里对vi中的一些常用操作作一下总结. 1.进入vi命令 vi filename: 打开或新建文件,并将光标置于第一行首 进入文件后,处于命令行模式(comman ...

  4. 以前编写的inno setup脚本,涵盖了自定义安装界面,调用dll等等应用 (转)

    以前编写的inno setup脚本,涵盖了自定义安装界面,调用dll等等应用 (转) ; Script generated by the Inno Setup 脚本向导. ; SEE THE DOCU ...

  5. 我所了解的 京东、携程、eBay、小米 的 OpenStack 云

    参加过几次 OpenStack meetup 活动,听过这几家公司的Architect 讲他们公司的 OpenStack产品.本文试着凭借影响加网络搜索,按照自己的理解,对这些公司的 OpenStac ...

  6. LeetCode(二)

    实现Trie树 class TrieNode { public char val; public boolean isWord; public TrieNode[] children = new Tr ...

  7. Android Log介绍

    android.util.Log常用的方法有以下5个:Log.v() ,Log.d() ,Log.i() ,Log.w() ,Log.e() .按照日志级别从高到低为ERROR, WARN, INFO ...

  8. $("<div />")代表的意思

    $("div")这个是匹配所有叫div的标签. $("<div />")表示生成一个div节点,但是div节点一般不通过这种方式,<div/& ...

  9. iOS.ReactNative-4-react-native-command-line-tool

    Command line tool: react-native 1. react-native 是一个命令行工具 1.1 react-native简介 运行以下命令: ls -lt `which re ...

  10. php get_magic_quotes_gpc()函数

    magic_quotes_gpc函数在php中的作用是判断解析用户提示的数据,如包括有:post.get.cookie过来的数据增加转义字符“\”,以确保这些数据不会引起程序,特别是数据库语句因为特殊 ...