新技能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. 关于 this 和 prototype 的理解

    1:this 的理解比较好的书是 <Javascript语言精粹> 平时我们全局写 var a = 1, 其实就是 window.a = 1; var f = function(){},  ...

  2. ted be grateful

    -------------------------------------------------------------- David Steindl-Rast: Want to be happy? ...

  3. 在C#中创建和读取XML文件

    1.创建简单的XML文件 为了便于测试,我们首先创建控制台应用程序,项目命名为CreateXml,Program.cs代码如下: 这样会在C盘根目录下创建data2.xml文件,文件内容为 using ...

  4. SVM3 Soft Margin SVM

    之前分为两部分讨论过SVM.第一部分讨论了线性SVM,并且针对线性不可分的数据,把原始的问题转化为对偶的SVM求解.http://www.cnblogs.com/futurehau/p/6143178 ...

  5. Bias and Variance

    以下内容参考 cousera 吴恩达 机器学习课程 1. Bias 和 Variance 的定义 Bias and Variance 对于改进算法具有很大的帮助作用,在bias和Variance的指引 ...

  6. java.lang.UnsupportedClassVersionError: xxx/xxxClass : Unsupported major.minor version 51.0

    完全参考自 http://www.cnblogs.com/xing901022/p/4172410.html 这种错误的全部报错信息: 1 java.lang.UnsupportedClassVers ...

  7. instancetype、id、NSObject的联系和区别

    1.id和instancetype都能省去具体类型,提高代码的通用性.而NSObject *则没有这种功能. 2.instancetype只能用于方法的返回类型,而id用处和NSObject *类似. ...

  8. python学习之——计算文件行数

    # -*- coding: cp936 -*- #转载源于:http://blog.csdn.net/houyj1986/article/details/21196027 #计算文件行数 #1.文件比 ...

  9. mormot THttpApiServer使用例子

    mormot THttpApiServer使用例子 THttpApiServer封装了WINDOWS的HTTPS.SYS. unit Unit1; interface uses Winapi.Wind ...

  10. javascript学习第三课引用类型object

    主要内容: 1.object 是所有类型的基类 实例化对象: 1. var obj = new Object(); 2. var obj = {}; 设置对象属性和方法: obj.name = 'he ...