0. 删除vector中的指定元素

今天来探讨C++中的一个基础问题。如何正确地删除vector中符合条件的某元素。比如,有一个vector<int> nums = {1, 2, 2, 2, 2, 3, 5},要求删除nums中所有值为2的元素。C++初学者可能很快就写出代码:

for (vector<int>::iterator it = nums.begin(); it != nums.end(); it++) {if (*it == 2) {nums.erase(it);}
}

这段代码循环遍历nums中的每个元素,判断是否为2,是的话则erase掉。看起来好像没什么问题,但是实际上已经造成了bug。这段代码的执行完成后,nums存储的元素是{1, 2, 2, 3, 5},值为2的元素并没有被全部清除掉,这个结果大家可以自己试验一下。

为什么会出现这个结果呢?原因就是迭代器失效:在第一个2被erase掉的时候,it迭代器已经失效了,用它来继续遍历vector就会漏掉被删除元素后面的第一个元素,导致2没有被完全清除。迭代器失效的原因与vector的内存管理策略有关,比较简单,网上资料很多,大家可以搜一下看看。这里我们重点关注如何正确的使用erase删除指定元素。

1. 重置迭代器为begin

既然在第一次删除2的时候,迭代器已经失效了,那么我们可以在失效后,重置迭代器为begin,再次进行遍历。代码如下:

for (vector<int>::iterator it = nums.begin(); it != nums.end();) {if (*it == 2) {nums.erase(it);it = nums.begin();} else {++it;}
}

这样写可以实现我们的需求,且没有bug。但是如果在工作中真这么写,你可能会被同事鄙视死!为什么呢?因为这段代码无谓地增加了时间复杂度,每删除一个元素,就要从头开始遍历,本来O(n)时间可以搞定的事情,现在却需要O(n^2)时间。那么还有没有更好的方案呢?当然是有的!

2. 让it指向下一个元素

查一下C plus plus网站,我们发现erase函数的返回值是指向当前被删除元素的下一个元素的迭代器。那么我们把这个返回值赋值给it继续遍历不就行了?代码如下:

for (vector<int>::iterator it = nums.begin(); it != nums.end();) {if (*it == 2) {it = nums.erase(it);} else {++it;}
}

这段代码可以在O(n)的时间内删除所有值为2的元素了,嗯,这下你的同事应该满意了!

3. 错误示范

对于上面这种写法,新手还有可能写出其他bug来,比如下面这段代码:

for (…) {if (condition1) continue;else if (condition2) it = vec.erase(it);else ++it;
}

这段代码存在非常严重的bug!如果condition1有一次为真而continue,it又没有继续递增,那么condition1永远为真,程序直接就陷入了死循环,再也出不来了。这个错误要注意避免!

同理,在循环中向vector insert或者push_back元素的时候也一定要注意迭代器失效造成的问题。

THE END

如何正确删除vector中的元素相关推荐

  1. 【C++基础】删除vector中指定下标元素

    [C++基础]删除vector中指定下标元素 vector<int> nums(n);1. 删除指定一个 i, auto it = nums.begin(); nums.erase(it+ ...

  2. 如何正确遍历删除List中的元素,你会吗?

    遍历删除List中的元素有很多种方法,当运用不当的时候就会产生问题.下面主要看看以下几种遍历删除List中元素的形式: 1.通过增强的for循环删除符合条件的多个元素 2.通过增强的for循环删除符合 ...

  3. python for 循环中使用 remove 删除列表中的元素

    python for 循环中使用 remove 删除列表中的元素 错误的代码 # !/usr/bin/python # encoding: utf-8 # -*- coding: utf8 -*- o ...

  4. 循环的时候去删除集合中的元素 java.util.ConcurrentModificationException

    使用for循环,删除集合中的元素,会报错 java.util.ConcurrentModificationException 只能通过迭代器 iterator删除 1:在while循环中使用itera ...

  5. java 删除list_Java中如何优雅地删除List中的元素

    在工作中的许多场景下,我们都会使用到List这个数据结构,那么同样的有很多场景下需要删除List中的某一个元素或某几个元素,那么我们该如何正确无误地删除List中的元素的,今天我来教大家三种方式. 前 ...

  6. 删除集合中特定元素的几种情况

    从集合中删除元素一直是一个比较容易遗漏的知识点,今天来给大家介绍一下删除集合​​中特定元素的一些情况. ​(一)List如何实现遍历删除 以ArrayList为例 List<String> ...

  7. Python中删除set中指定元素元素不存在时不报错:s.discard()元素不存在时报错:s.remove()

    [小白从小学Python.C.Java] [Python-计算机等级考试二级] [Python-数据分析] Python中删除set中指定元素 元素不存在时不报错:s.discard() 元素不存在时 ...

  8. PageCollectionView[Bug],使用Filter的时候,删除集合中的元素,会导致ArgumentOutOfRangeException...

    PageCollectionView,没有使用Filter的时候一切正常:当使用Filter的时候,删除集合中的元素,会抛出如下异常: 1: 指定的参数已超出有效值的范围.\n参数名: index 2 ...

  9. java删除集合元素吗_java如何删除集合中的元素

    java如何删除集合中的元素 如何使用java删除集合中的'元素呢?下面是小编给大家提供的删除集合中元素的常见方法,欢迎阅读,更多详情请关注应届毕业生考试网. Java代码如下: package co ...

最新文章

  1. JDK5.0新特性系列---目录
  2. 2015年阿里实习生面试Java研发工程师 小记
  3. 用Maven构建Mahout项目
  4. 创建交叉表_质性数据分析软件NVivo教程:交叉表查询
  5. CHIL-SQL-PRIMARY KEY 约束
  6. Linux内核的时钟中断
  7. c# out原理 ref_移植贪吃蛇——从C#到C++
  8. 大数据集群被窃取数据怎么办?透明加密可以一试
  9. 无心剑随感《爱心教育》
  10. 主机和虚拟机复制粘贴失效的解决方案
  11. UG NX 12 草图环境中使用鼠标的说明
  12. ROS学习笔记(一)#ROS系统及RoboWare的安装
  13. android渠道首发规则,酷传推广标准手册-android渠道首发规则.doc
  14. 【Java编程系列】java用POI、Itext生成并下载PPT、PDF文件
  15. 给定数字0-9各若干个。你可以以任意顺序排列这些数字,但必须全部使用。目标是使得最后得到的数尽可能小(注意0不能做首位)
  16. 台湾SSS鑫创SSS1700替代Cmedia CM6533 24bit 96KHZ USB音频编解码芯片
  17. 「安全系列之CSRF」如何防范csrf攻击
  18. 什么是java变量,java变量的定义
  19. Origin Pro2017使用PatchOriginPro.exe破解提示Patch unsuccessfully or already
  20. BlogBus发难:博客为什么不能随便搬家?

热门文章

  1. python keys模块_python自动化常用模块
  2. windows游戏命令行
  3. 安装,配置rp-pppoe拨号软件,使adsl成功上网(转)
  4. 金蝶EAS系统,凭证接口,凭证重复,系统已经引入过凭证
  5. 3DS文件在OpenGL的读入和显示
  6. 《密码编码学与网络安全》复习总结
  7. ios swift 聊天_iOS Swift上的加密聊天
  8. 《三易通服装进销存软件》项目研发阶段性总结
  9. 漏洞标题: 中国移动mas2.0平台系统漏洞
  10. 初识安卓--简单计算器(上)