令人疑惑的 std::remove 算法

摘自《Effective STL》第32条

remove的声明:

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

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

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

 1 #include <iostream>
 2 #include <memory>
 3 #include <vector>
 4 #include <algorithm>
 5
 6 using namespace std;
 7
 8 int main()
 9 {
10     vector<int> 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 : 10
size : 10

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

remove 到底做了什么?

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

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

调用 remove 之后:

vector<int>::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)。

可以使用智能指针。

时间: 2024-11-05 21:47:41

令人疑惑的 std::remove 算法的相关文章

实战c++中的vector系列--对vector&amp;lt;自己定义类&amp;gt;使用std::find 和 std::find_if 算法

之前博客讲了一些关于std::find和std::find_ if的一些使用方法.可是没有讲述对于vector中存储的是自己定义的类.那么怎么样使用std::find和std::find_if进行查找呢? 先定义一个类: class Item { private: std::string m_ItemId; int m_Price; int m_Count; public: Item(std::string id, int price, int count): m_ItemId(id), m_C

实战c++中的vector系列--对vector&lt;自定义类&gt;使用std::find 和 std::find_if 算法

之前博客讲了一些关于std::find和std::find_ if的一些用法,但是没有讲述对于vector中存储的是自定义的类,那么怎么样使用std::find和std::find_if进行查找呢? 先定义一个类: class Item { private: std::string m_ItemId; int m_Price; int m_Count; public: Item(std::string id, int price, int count): m_ItemId(id), m_Coun

令人疑惑的问题

1.在MFC中有一段代码,这么写就有问题 1 CString IPstr = inet_ntoa(*((in_addr *)pHost->h_addr)); 这么写就没问题 1 CString IPstr; 2 IPstr = inet_ntoa(*((in_addr *)pHost->h_addr)); 为啥嘞?

STL源码剖析——STL算法之remove删除算法

前言 由于在前文的<STL算法剖析>中,源码剖析非常多,不方便学习,也不方便以后复习,这里把这些算法进行归类,对他们单独的源码剖析进行讲解.本文介绍的STL算法中的remove删除算法,源码中介绍了函数remove.remove_copy.remove_if.remove_copy_if.unique.unique_copy.并对这些函数的源码进行详细的剖析,并适当给出使用例子,具体详见下面源码剖析. remove移除算法源码剖析 // remove, remove_if, remove_co

C++ - STL常用算法-sort、find、count、等等【还有remove......暂时不写】

起始算法有很多,或者说太多,这里不写了,主要写一写在 vector deque stack queue set map 中出现过的算法,其他算法,以后在此补充! 这些算法使用时候,包含:#include<algorithm> 其余算法参考:https://blog.csdn.net/tick_tock97/article/details/71316372 在线手册:http://www.cplusplus.com/reference/algorithm 一.sort 没有返回值: 1 std:

std::sort源码剖析

文章参考:源码 这篇文章在一个偶然的机会看到,我原先也是知道sort函数效率高,但终究没有去了解原因,读了这篇文章更加钦佩C++大师积年累月智慧的结晶和对效率的极致追求,看到很多地方不禁暗暗称奇.也还是感慨原文作者对技术的追求和细致的讲解,下面的内容大多来自作者的文章,其中加入了自己的理解,也不枉费大半个下午的时间. 从事程序设计行业的朋友一定对排序不陌生,它从我们刚刚接触数据结构课程开始便伴随我们左右,是需要掌握的重要技能.任何一本数据结构的教科书一定会介绍各种各样的排序算法,比如最简单的冒泡

stl变易算法(三)

本篇接着前面stl变易算法(一)和stl变易算法(二)继续讲述变易算法. 这里将介绍完余下的变易算法,主要有:填充fill.n次填充fill_n.随机生成元素generate.随机生成n个元素generate_n.移除复制remove_copy.条件移除复制remove_copy_if.移除remove.条件移除remove_if.不连续反复元素复制unique_copy.剔除连续反复元素unique.元素反向reverse.反向复制reverse_copy及旋转rotate .给出算法实现及实

STL源码剖析——STL算法stl_algo.h

前言 在前面的博文中剖析了STL的数值算法.基本算法和set集合算法,本文剖析STL其他的算法,例如排序算法.合并算法.查找算法等等.在剖析的时候,会针对函数给出一些例子说明函数的使用.源码出自SGI STL中的<stl_algo.h>文件.注:本文的源码非常多,可能后续博文会对这些算法进行归类分析. STL算法剖析 #ifndef __SGI_STL_INTERNAL_ALGO_H #define __SGI_STL_INTERNAL_ALGO_H #include <stl_heap

algorithm之改变序列算法

简述:改变序列算法,参见http://www.cplusplus.com/reference/algorithm/?kw=algorithm /* template <class BidirectionalIterator, class UnaryPredicate> BidirectionalIterator partition (BidirectionalIterator first, BidirectionalIterator last, UnaryPredicate pred); Pa