新技能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. "Asp.Net Web Api MediaTypeFormatter Error for x-www-formurlencoded data" 解决方法

    遇到标题中所说的问题原因是使用 jQuery AJAX 以 POST 方式调用 Asp.Net Web API .解决办法请看以下代码中有注释的部分. public static class WebA ...

  2. JQuery中$(document)是什么意思有什么作用

    $(document).ready(fn):当DOM载入就绪可以查询及操纵时绑定一个要执行的函数,因为它可以极大地提高web应用程序的响应速度 首先我解释一下jQuery jQuery有一个用来作为D ...

  3. java文件末尾追加内容的两种方式

    java 开发中,偶尔会遇到在文件末尾对文件内容进行追加,实际上有多种方式可以实现,简单介绍两种: 一种是通过RandomAccessFile类实现,另一种是通过FileWriter类来实现. 实现方 ...

  4. zabbix快速安装

    运维什么的其实感觉根本没有什么好写的了,因为太简单了嘛,尤其是这个监控,整得那么麻烦要干嘛,不过貌似很多人喜欢这个,我就随手写一点吧 环境:centos7.2.1511最简安装,就是什么都不选直接就开 ...

  5. iOS开发之AFNetworking 3.0.4使用-OC

      GET请求 AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; [manager GET:URL parameters: ...

  6. 咏南WEB开发框架(FOR XE10.1 BERLIN)

    咏南WEB开发框架(FOR XE10.1 BERLIN) 1)支持最新的XE10.1 BERLIN开发WEB程序 2)如同开发VCL WIN32程序一样的速度 3)WEB框架通过咏南中间件和数据库打交 ...

  7. 怎样把windows中安装的程序列出来?

    症状/问题我怎样把windows中安装的程序信息输出到一个文本文件中?解决方法使用 windows 操作系统中的命令:wmic就可以做到.下面的命令就可以把系统中安装的程序都输出到文件ProgramL ...

  8. Mac上的抓包工具Charles

    http://blog.csdn.net/jiangwei0910410003/article/details/41620363 $********************************** ...

  9. 关于最近在做的一个js全屏轮播插件

    最近去面试了,对方要求我在一个星期内用原生的js代码写一个全屏轮播的插件,第一想法就是跟照片轮播很相似,只是照片轮播是有定义一个宽高度大小已经确定了的容器用来存储所有照片,然后将照片全部左浮动,利用m ...

  10. Web前台直接加载GIS格式数据分析

    本文以Flex直接加载Shp.DWG和MDB为例. 首先看一份现估测数据: 1)  加载Shp文件,目前直接由前台Flex代码完成: 图1 在ArcCatalog里面的Shp文件 图2 直接在前台加载 ...