C++ vector erase函数

最近使用了顺序容器的删除元素操作,特此记录下该函数的注意事项。

在C++primer中对c.erase(p) 这样解释的:

 c.erase(p)    删除迭代器p所指向的元素,返回一个指向被删元素之后元素的迭代器,若p指向尾元素,则返回尾后迭代器,若p是尾后迭代器,则会产生未定义行为。

这个函数我在使用的过程中发现有那么一点小小的注意事项

如果要想遍历一个容器,并且删除某个不符合要求的元素,那么最好使用while而不是使用for

因为

        vector<RotatedRect>::iterator  it = m_rect.begin();while((it) !=m_rect.end())
        {float diff = abs((*it).size.width - (*(it + 1)).size.width);if( diff > diffmax)
           {if(( it - m_rect.begin())  < (m_rect.size() / 2))   it = m_rect.erase(it); //此时指针已经指向下一个元素,故指针不需要再自增else   it = m_rect.erase(it + 1); }else{it++; //否则指针自增一,while循环可以选择有条件的让指针指向下一个元素}}    
    vector<RotatedRect>::iterator  it = m_rect.begin();for( ;(it) != m_rect.end(); it++ )  //如果使用for循环,并且选择在此处自增一
       {float diff = abs((*it).size.width - (*(it + 1)).size.width);if( diff > diffmax){if(( it - m_rect.begin())  < (m_rect.size() / 2))   it = m_rect.erase(it); //那么将会与这里的自增重复,这样会造成有元素被跳过else   it = m_rect.erase(it + 1); }}    

我在查阅资料时发现有个博主推荐的写法是这样的

此处链接http://blog.csdn.net/zhuimengzh/article/details/6841500

void fun(){vector<int> iVec;vector<int>::iterator it;for(int i=0;i<10;i++)iVec.push_back(i);display(iVec);for(it=iVec.begin();it!=iVec.end();++it){if(*it ==4 || *it == 7){it=iVec.erase(it);--it;//这里回退一个       //******该博主推荐在此处自动回退一个,这样貌似可以用for循环了,但是其实不是的
}}display(iVec);}

如果你删除的元素是容器的第一个元素,那么回退的行为将是未定义的,切记

c++ vector begin(),end(),rbegin(),rend()问题

C++ primer (中文版第四版)第273页

9.3.2 begin和end成员

begin和end操作产生指向“容器内第一个元素” 和 “最后一个元素的下一个位置的迭代器”。这两个迭代器通常用于标记包含容器中所有元素的迭代范围。

c.begin() 返回一个迭代器,它指向容器c的第一个元素

c.end() 返回一个迭代器,它指向容器c的最后一个元素的下一个位置

c.rbegin() 返回一个逆序迭代器,它指向容器c的最后一个元素

c.rend() 返回一个逆序迭代器,它指向容器c的第一个元素前面的位置

上述每个操作都有两个不同的版本:一个是const成员,另一个是非const成员。这些操作返回什么类型取决于容器是否为const。如果容器不是const,则这些操作返回iterator或reverse_iterator类型。如果容器是const,则其返回类型要加上const_前缀,也就是const_iterator和const_reverse_iterator类型。

第353页

11.3.3 反向迭代器

反向迭代器是一种反向遍历容器的迭代器。也就是,从最后一个元素到第一个元素遍历容器。反向迭代器将自增(和自减)的含义反过来了:对于反向迭代器,++ 运算将访问前一个元素,而 -- 运算则访问下一个元素。

回想一下,所有容器都定义了 begin 和 end 成员,分别返回指向容器首元素和尾元素下一位置的迭代器。容器还定义了 rbegin 和 rend 成员,分别返回指向容器尾元素和首元素前一位置的反向迭代器。与普通迭代器一样,反向迭代器也有常量(const)和非常量(nonconst)类型。图 11.1 使用一个假设名为 vec 的 vector 类型对象阐明了这四种迭代器之间的关系。

图 1 比较 begin/end 和 rbegin/rend 迭代器

假设有一个 vector 容器对象,存储 0-9 这 10 个以升序排列的数字:

[html] view plain copy
  1. vector<int> vec;
  2. for (vector<int>::size_type i = 0; i != 10; ++i)
  3. vec.push_back(i); // elements are 0,1,2,...9

下面的 for 循环将以逆序输出这些元素:

[html] view plain copy
  1. // reverse iterator of vector from back to front
  2. vector<int>::reverse_iterator r_iter;
  3. for (r_iter = vec.rbegin(); // binds r_iter to last element
  4. r_iter != vec.rend(); // rend refers 1 before 1st element
  5. ++r_iter) // decrements iterator one element
  6. cout << *r_iter << endl; // prints 9,8,7,...0

虽然颠倒自增和自减这两个操作符的意义似乎容易使人迷惑,但是它让程序员可以透明地向前或向后处理容器。

例如,为了以降序排列 vector,只需向 sort传递一对反向迭代器:

[html] view plain copy
  1. // sorts vec in "normal" order
  2. sort(vec.begin(), vec.end());
  3. // sorts in reverse: puts smallest element at the end of vec
  4. sort(vec.rbegin(), vec.rend());

1.反向迭代器需要使用自减操作符

从一个既支持 -- 也支持 ++ 的迭代器就可以定义反向迭代器,这不用感到吃惊。毕竟,反向迭代器的目的是移动迭代器反向遍历序列。标准容器上的迭代器既支持自增运算,也支持自减运算。但是,流迭代器却不然,由于不能反向遍历流,因此流迭代器不能创建反向迭代器。

流迭代器:https://www.cnblogs.com/ll-10/p/5461374.html 【流迭代器是一种迭代器适配器。istream_iterator用于读取输入流,ostream_iterator用于写输出流。这些迭代器将它们所对应的流视为特定类型的元素序列。使用流迭代器时,可以用泛型算法从流对象中读数据或将数据写入到流对象中。】

2.反向迭代器与其他迭代器之间的关系
      假设有一个名为 line 的 string 对象,存储以逗号分隔的单词列表。我们希望输出 line 中的第一个单词。使用 find 可很简单地实现这个任务:

[html] view plain copy
  1. // find first element in a comma-separated list
  2. string::iterator comma = find(line.begin(), line.end(), ',');
  3. cout << string(line.begin(), comma) << endl;

如果在 line 中有一个逗号,则 comma 指向这个逗号;否则,comma 的值为 line.end()。在输出 string 对象中从 line.begin() 到 comma 的内容时,从头开始输出字符直到遇到逗号为止。如果该 string 对象中没有逗号,则输出整个 string 字符串。
      如果要输出列表中最后一个单词,可使用反向迭代器:

[html] view plain copy
  1. // find last element in a comma-separated list
  2. string::reverse_iterator rcomma = find(line.rbegin(), line.rend(), ',');

因为此时传递的是 rbegin() 和 rend(),这个函数调用从 line 的最后一个字符开始往回搜索。当 find 完成时,如果列表中有逗号,那么 rcomma 指向其最后一个逗号,即指向反向搜索找到的第一个逗号。如果没有逗号,则 rcomma 的值为 line.rend()。
      在尝试输出所找到的单词时,有趣的事情发生了。直接尝试:

[html] view plain copy
  1. // wrong: will generate the word in reverse order
  2. cout << string(line.rbegin(), rcomma) << endl;

会产生假的输出。例如,如果输入是:
      FIRST,MIDDLE,LAST
则将输出 TSAL!

图 2 阐明了这个问题:使用反向迭代器时,以逆序从后向前处理 string对象。为了得到正确的输出,必须将反向迭代器 line.rbegin() 和 rcomma 转换为从前向后移动的普通迭代器。其实没必要转换 line.rbegin(),因为我们知道转换的结果必定是 line.end()。只需调用所有反向迭代器类型都提供的成员
函数 base 转换 rcomma 即可:

[html] view plain copy
  1. // ok: get a forward iterator and read to end of line
  2. cout << string(rcomma.base(), line.end()) << endl;

假设还是前面给出的输入,该语句将如愿输出 LAST。

图 2. 反向迭代器与普通迭代器之间的区别

图 2 显示的对象直观地解释了普通迭代器与反向迭代器之间的关系。例如,正如 line_rbegin() 和 line.end() 一样,rcomma 和 rcomma.base() 也指向不同的元素。为了确保正向和反向处理元素的范围相同,这些区别必要的。从技术上来说,设计普通迭代器与反向迭代器之间的关系是为了适应左闭合范围(第 9.2.1 节)这个性质的,所以,[line.rbegin(), rcomma) 和[rcomma.base(), line.end()) 标记的是 line 中的相同元素。

反向迭代器用于表示范围,而所表示的范围是不对称的,这个事实可推导出一个重要的结论:

使用普通的迭代器对反向迭代器进行初始化或赋值时,所得到的迭代器并不是指向原迭代器所指向的元素。

C++ Vector 汇总相关推荐

  1. 你真的懂数据分析吗?一文读懂数据分析的流程、基本方法和实践

    导读:无论你的工作内容是什么,掌握一定的数据分析能力,都可以帮你更好的认识世界,更好的提升工作效率.数据分析除了包含传统意义上的统计分析之外,也包含寻找有效特征.进行机器学习建模的过程,以及探索数据价 ...

  2. matlab vector用法,C++ vector 用法汇总

    标准库Vector类型 使用需要的头文件: #include Vector:Vector 是一个类模板.不是一种数据类型. Vector是一种数据类型. 一.  定义和初始化 Vectorv1;    ...

  3. MFC中STL容器中Vector,List,Map基本用法汇总

    容器就是数据结构的泛指,迭代器就是指针的泛指,可以指向元素.它可以用来存储数据,就比如杯子用来装水一样.而STL中的容器有很多,它包括vector,list,map,deque,set等.我就简单列举 ...

  4. C++ vector 遍历修改汇总

    通过迭代器.下标操作符.范围for三种方式遍历vector内部元素以及不同遍历方式修改元素. #include<iostream> #include<vector> using ...

  5. [转载] c++的vector赋值方法汇总

    参考链接: C++ : generate生成随机数为Vector赋值 #include <iostream> #include <vector> using namespace ...

  6. 词向量化 Vector Representation of Words 方法汇总

    PART I: Classical Machine Leaning 为什么要进行词向量化? "向量化"可以理解为"数值化",为什么要"数值化" ...

  7. 特征点匹配+特征检测方法汇总

    特征点匹配+特征检测方法汇总 特征提取与匹配---SURF:SIFT:ORB:FAST:Harris角点 匹配方法 匹配函数 1. OpenCV提供了两种Matching方式: • Brute-for ...

  8. C/C++各种数据类型转换汇总

    以下是Windows/Linux系统中常用的C/C++各种数据类型转换汇总: #ifndef FBC_MESSY_TEST_DATA_TYPE_CONVERT_HPP_ #define FBC_MES ...

  9. 上手!深度学习最常见的26个模型练习项目汇总

    作者:沧笙踏歌 转载自AI部落联盟(id:AI_Tribe) 今天更新关于常见深度学习模型适合练手的项目.这些项目大部分是我之前整理的,基本上都看过,大概俩特点:代码不长,一般50-200行代码,建议 ...

最新文章

  1. sqlite-1.0.0源码执行的基本流程概述
  2. Android环境的构建
  3. CDN监控系统(一)
  4. Java实现Zip文件解压
  5. IntelliJ IDEA scala的源码设置
  6. 吃亏受苦、前途未卜,Nature调查显示博士生三分之一可能抑郁
  7. linux命令history作用,Linux命令:history命令历史的管理及用法
  8. 如何下载安装Photoshop cs 6(供新手)
  9. JAVA命令行运行时设置参数
  10. 百度文库和豆丁网的在线文档阅读功能
  11. 中兴f477v2超级管理员_[求助] 联通光猫 ZXHN F477V2 桥接问题
  12. 结构化程序设计(structured programming)
  13. html如何设置按钮背景为透明,css 设置按钮(背景色渐变、背景色透明)
  14. [架构]京东咚咚架构演进
  15. 解决ffmpeg合并视频后播放条拖不动,画面出错的问题
  16. 神武3登录显示未能成功连接服务器,T3安装成功后,点击运行显示登录界面,但提示“检测公共组件Protal。exe时未能通过,公共组件可能被破坏”,和”无法连接服务器“。应该怎么处理?求助!...
  17. linux程序设计项目报告,Linux程序设计实验报告大作业
  18. 超链接 a标签 虚线框 虚线 去除虚线框
  19. 国外计算机cpu排行,电脑处理器排行榜_电脑处理器排行榜最新2020
  20. stata合并多张箱线图的命令

热门文章

  1. NGINX 配置超时时间
  2. Python基础-变量作用域
  3. 【BZOJ 4169】 4169: Lmc的游戏 (树形DP)
  4. Hibernate读书笔记
  5. 感知机模型的对偶形式[转载]
  6. 自定义SeekBar 实时显示百分比进度
  7. 手机影音第十一天,显示视频缓冲,显示卡顿时的网速,播放系统视频时调用播放器的选择...
  8. 1-3-顺时针旋转矩阵
  9. iOS开发-Get请求,Post请求,同步请求和异步请求
  10. 话里话外: 信息化与高层参与度的关系