新技能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. js判断是否安装pdf播放器

    function isPDFPluginInstall() { if (!isIE()) { //ie 浏览器 和 非ie浏览器支持 // not ie if (navigator.plugins & ...

  2. WPS项目编号问题

    问题:文档需要编号如下: 1.(标题1) 1.1(标题2) 1.1.1(标题3) 1.2 1.2.1 2.(标题1) 2.1(标题2) 2.1.1(标题3) 2.2 2.2.1 方法一: 第一步,打开 ...

  3. 使用阿里Docker镜像加速器加速

    在阿里开发者平台注册开发者账号 https://dev.aliyun.com/search.html 注册之后可以访问Docker镜像服务 https://cr.console.aliyun.com/ ...

  4. Git版本控制教程

    Git 版本控制入门 不了解Git请查看权威Git书籍 ProGit(中文版). 一份很好的 Git 入门教程,点击这里查看. Git客户端下载地址: 官方Git - TortoiseGit - So ...

  5. 第12章 在.NET中操作XML

    12.1 XML概述 12.1.1 为什么要有XML 12.1.2 XML文档结构 (1)文档声明 <?xml version="1.0"encoding="UTF ...

  6. (引用)web安全测试

    转载:http://www.51testing.com/html/44/15020244-908645.html Web安全测试之XSS XSS 全称(Cross Site Scripting) 跨站 ...

  7. Pig Latin

    function translate(str) { //return str; var list = ['a','e','i','o','u']; if(list.indexOf(str[0]) &g ...

  8. js获取文件大小

    var file = urlBox.doc.activeElement.files[0]||urlBox.files[0] ; if (file) { var fileSize = 0; if (fi ...

  9. poj1166学习中

    #include <iostream> #include <string.h> #include <cstdio> #include <cmath> u ...

  10. (Python)集合、集合的函数

    本节我们将学习python的另一种数据类型:集合(set) 1.集合(set) 集合在Python中是一种没有重复元素,且无序的数据类型,且不能通过索引来引用集合中的元素 >>> b ...