博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
在vector的循环中调用erase
阅读量:5134 次
发布时间:2019-06-13

本文共 1198 字,大约阅读时间需要 3 分钟。

    在使用vector的过程中,有时会遇到需要循环遍历vector,并删除符合指定条件的元素。

    当“指定条件”不复杂时,应该尽量使用erase(remove_if(begin, end, func), end)的形式来完成功能。

    但有时候“指定条件”过于复杂,不得不显式地写一个for循环来处理。我们必须小心在意erase所带来的side effect,一个一般性的for循环如下:

1 for (std::vector
::iterator it = intVec.begin(); it != intVec.end(); /**/) 2 { 3 if (*it == 3) 4 { 5 intVec.erase(it); 6 } 7 else 8 { 9 ++it;10 }11 }

    所要注意的是it = intVec.erase(it)。实际上这里如果写成intVec.erase(it),即不对it做重新赋值,代码也能正常执行,特别是release版本几乎所有的编译器编译后都能产生结果正确的代码。而debug模式下有一些较新的编译器会在编译时给出警告,并在运行时出现断言错误。

    为什么一个错误的写法在大多数情况下都能得到正确的答案?

    根据STL的描述,执行erase(it)后,itit之后的迭代器都可能会失效。这一点很好理解。因为vector一般由动态数组实现,它的元素在内存中是连续存储的。当删除掉it所指向元素时,原本在it后面的元素需要集体前移。迭代器本身几乎可以理解为是一个指针,在erase之后它所指向的位置并没有变化,只是那个位置的元素发生了变化,而且恰好变成了我们所想要的。至少大多数STL版本是这么实现的,因为这处理起来比较自然。

    然而我们不能依赖于这个一般性事实,而应该采用it=intVec.erase(it)的形式来对it重新赋值。STL中有要求vectorerase函数要返回指向被erase的迭代器的下一个位置,写成it=intVec.erase(it)是万无一失的,而写成intVec.erase(it)虽然实际可行,但是具有潜在风险,万一某一天erase会影响it的指向(STL只要求erase移除元素,而没有保证it自身不变),程序就极有可能出问题。

    根据标准所描述的约束来编程,而不是根据具体的实现细节来编程。

    对于C++ STL,似乎有很多个版本的实现,而它们或多或少都有所偏差。这里有两个网站,可以进行参考:

转载于:https://www.cnblogs.com/carter2000/archive/2012/04/19/2458215.html

你可能感兴趣的文章
java学习
查看>>
NYOJ 448 素数环
查看>>
分析Linux 0.11中的kernel部分的makefile文件
查看>>
POJ-2226 Muddy Fields 最小点集覆盖
查看>>
docker社区的geodata/gdal镜像dockerfile分析
查看>>
【leetcode】Edit Distance
查看>>
python--集合
查看>>
高精度计时器 -- C++/Windows版
查看>>
Vue v-on v-model 组合使用
查看>>
java OO
查看>>
H5活动页开发有关
查看>>
IOS调试使用技巧
查看>>
JAVA之多线程概念及其几种实现方法优劣分析
查看>>
python3.6+selenium_发送邮件(包含自动生成的测试报告)
查看>>
POJ 1006 同余方程组
查看>>
javascript时间差工具包
查看>>
TCP/IP 基础简介
查看>>
页面中部分标签简单描述
查看>>
GIT 远程仓库
查看>>
[工具]Visual Studio
查看>>