博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
令人疑惑的 std::remove 算法
阅读量:4586 次
发布时间:2019-06-09

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

摘自《Effective STL》第32条

remove的声明:

1 template
2 ForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value);

如同所有的算法一样,remove 也需要一对迭代器来指定所要进行操作的元素区间。它并不接受容器作为参数,所以 remove 并不知道这些元素被存放在哪个容器中。并且,remove 也并不能从迭代器推知对应的容器和容器类型。

唯一可以从容器中删除元素的方法是调用容器的成员函数 erase (list有几个可以删除元素的成员函数,但是没有命名为 erase)。remove 算法并不知道它操作的元素的所在容器,所以不可能从容器中删除元素。

1 #include 
2 #include
3 #include
4 #include
5 6 using namespace std; 7 8 int main() 9 {10 vector
c = {
1,2,3,4,5,6,7,8,9,1};11 cout << "size : " << c.size() << endl;12 13 remove(c.begin(), c.end(), 1);14 cout << "size : " << c.size() << endl;15 16 }

执行后显示:

size : 10size : 10

使用 remove 后,容器中的元素并没有减少。

remove 到底做了什么?

简而言之,remove 移动了区间中的元素。其结果是,“需要被删除”的元素被移到了区间的尾部。它返回一个迭代器,指向第一个“需要被删除”的元素。

调用 remove 之前,c 的布局如下:

调用 remove 之后:

vector
::iterator newEnd(remove(c.begin(), c.end(), 1));

c 的布局如下

你会发现最后两个元素的值没有发生变化。。。

这个是 remove 算法的附带结果。在内部,remove 遍历整个区间,用需要保留的元素的值覆盖掉那些要被删除的元素的值。这种覆盖是通过对那些需要被覆盖的元素的赋值来完成的。

 

因此,要想删除这些元素,必须调用区间形式的 erase。

还用两个类似的算法:remove_if  和 unique。都需要在调用 remove_if 和 unique 后调用 erase。

其中 list 的调用是不一致的,list::remove 会真正删除元素(并且比使用 erase-remove 习惯用法更加高效),list::unique 也会真正删除元素(并且比使用 erase-unique 更加高效)

 

注意:当容器中存放的是指向动态分配的对象的指针时,应该避免使用 remove 和类似的算法(remove_if 和 unique)。

可以使用智能指针。

转载于:https://www.cnblogs.com/jingyg/p/5613303.html

你可能感兴趣的文章
第一期_Nor Flash
查看>>
oracle 10g
查看>>
ecshop那些事
查看>>
Oracle复制表结构及数据
查看>>
javaweb实现添加课程
查看>>
andriod jbox2d学习笔记二 通过移动关节移动body
查看>>
python列表-简单操作
查看>>
NYOJ题目97兄弟郊游问题
查看>>
IIS web.config拒绝访问 未能开始监视对 XX 文件的更改
查看>>
Opengl编程指南第二章:状态管理、几何绘图
查看>>
二分查找——算法系列
查看>>
python中的命名
查看>>
读书印记 - 《大学潜规则:谁能优先进入美国顶尖大学》
查看>>
DFS Codeforces Round #306 (Div. 2) B. Preparing Olympiad
查看>>
K均值聚类
查看>>
[bzoj1568]李超线段树模板题(标志永久化)
查看>>
web基础,用html元素制作web页面
查看>>
[18/11/21] 方法
查看>>
遍历循环
查看>>
iframe跨域解决方案
查看>>