令人疑惑的 std::remove 算法
摘自《Effective STL》第32条
remove的声明:
template<class ForwardIterator, class T>
ForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value);
如同所有的算法一样,remove 也需要一对迭代器来指定所要进行操作的元素区间。它并不接受容器作为参数,所以 remove 并不知道这些元素被存放在哪个容器中。并且,remove 也并不能从迭代器推知对应的容器和容器类型。
唯一可以从容器中删除元素的方法是调用容器的成员函数 erase (list有几个可以删除元素的成员函数,但是没有命名为 erase)。remove 算法并不知道它操作的元素的所在容器,所以不可能从容器中删除元素。
#include <iostream>
#include <memory>
#include <vector>
#include <algorithm> using namespace std; int main()
{
vector<int> c = {,,,,,,,,,};
cout << "size : " << c.size() << endl; remove(c.begin(), c.end(), );
cout << "size : " << c.size() << endl; }
执行后显示:
size :
size :
使用 remove 后,容器中的元素并没有减少。
remove 到底做了什么?
简而言之,remove 移动了区间中的元素。其结果是,“需要被删除”的元素被移到了区间的尾部。它返回一个迭代器,指向第一个“需要被删除”的元素。
调用 remove 之前,c 的布局如下:

调用 remove 之后:
vector<int>::iterator newEnd(remove(c.begin(), c.end(), ));
c 的布局如下
你会发现最后两个元素的值没有发生变化。。。
这个是 remove 算法的附带结果。在内部,remove 遍历整个区间,用需要保留的元素的值覆盖掉那些要被删除的元素的值。这种覆盖是通过对那些需要被覆盖的元素的赋值来完成的。
因此,要想删除这些元素,必须调用区间形式的 erase。
还用两个类似的算法:remove_if 和 unique。都需要在调用 remove_if 和 unique 后调用 erase。
其中 list 的调用是不一致的,list::remove 会真正删除元素(并且比使用 erase-remove 习惯用法更加高效),list::unique 也会真正删除元素(并且比使用 erase-unique 更加高效)
注意:当容器中存放的是指向动态分配的对象的指针时,应该避免使用 remove 和类似的算法(remove_if 和 unique)。
可以使用智能指针。
令人疑惑的 std::remove 算法的更多相关文章
- 【翻译】std::remove - C++ Reference
函数模板 std::remove 头文件<algorithm> template <class ForwardIterator, class T> ForwardIterato ...
- JAVA中令人疑惑的字符串
Java中不同的字符串存在于同一个存储池中,字符串变量将指向存储池中相应的位置,也就是字符串变量里面包含的并不是字符串而是这个字符串对象的内存地址. String a = "123" ...
- C++ 标准库 std::remove
参见:https://zh.cppreference.com/w/cpp/algorithm/remove std::remove 不会改变输入vector / string 的长度.其过程,相当于去 ...
- std::remove
#include <algorithm> template< class ForwardIt, class T > ForwardIt remove( ForwardIt fi ...
- STL之算法使用简介
accumlate : iterator 对标志的序列中的元素之和,加到一个由 init 指定的初始值上.重载的版本不再做加法,而是传进来的二元操作符被应用到元素上. adjacent_differ ...
- 28.STL常用算法
#include <algorithm> 算法 常用版本 描述 返回Type std::find() find(_InIt _Fisrt,_InIt _Last, _Ty& _Va ...
- C++学习笔记-STL
C++ STL (Standard Template Library标准模板库) 是通用类模板和算法的集合,它提供给程序员一些标准的数据结构的实现如 queues(队列), lists(链表), 和 ...
- STL源代码分析——STL算法remove删除算法
前言 因为在前文的<STL算法剖析>中,源代码剖析许多.不方便学习,也不方便以后复习,这里把这些算法进行归类.对他们单独的源代码剖析进行解说.本文介绍的STL算法中的remove删除算法. ...
- STL区间成员函数及区间算法总结
STL区间成员函数及区间算法总结 在这里总结下可替代循环的区间成员函数和区间算法: 相比单元素遍历操作,使用区间成员函数的优势在于: 1)更少的函数调用 2)更少的元素移动 3)更少的内存分配 在区间 ...
随机推荐
- C#代码处理前台html标签拼接
之前一篇文章是写,JavaScript处理特殊字符拼接时截断问题.最近在处理公司老软件兼容性升级时碰到的一个类似的问题,这次是后台拼接字符串,前台.aspx页面显示的.中间走了两次弯路,在此记录一下. ...
- CDHtmlDialog探索----Javascript与窗体交互
CDHtmlDialog提供了C++与网页的双向交互,通此一系统简单的宏调用可以把网页中各元素的事件直接映射到C++程序中,而在网页中调用C++功能代码就显的不那么直观了.归根结底交互的基理就是实现相 ...
- HTML5在线预览PDF
简介 PDF.js is a Portable Document Format (PDF) viewer that is built with HTML5. PDF.js is community-d ...
- WPA简介
摘选自 https://www.sohu.com/a/199641521_683126 WPA 全名 WI-FI Protected Access, 有WPA 和WPA2两个标准,是一种保护无线网络的 ...
- $Django 路飞之课程下的分类,用户登陆成功前端存cookie,
一 课程分类显示 宗旨:总的再次过滤 二 Cookie # export default new Vuex.Store({ state: { name:'', token:'', }, mutatio ...
- 06 元祖 字典 集合set
元组 定义: ti=() print(ti,type(ti)) 参数:for可以循环的对象(可迭代对象) t2=tuple(") # ('1', '2', '3') <class 't ...
- hive学习05 参数设置
001参数设置 hive执行命令的本质是mapreduce,当然也可以作为关系型数据库进行查询 --设置一个job有多少个reducer处理,依据多少的是文件的大小,默认1G set hive.exe ...
- Confluence 6 Windows 中以服务方式自动重启修改运行服务的用户
基于安全的考虑,如果你希望你的 Confluence 不是在系统中以管理员的身份运行或者你使用网络驱动器来存储备份,附件和索引的话,你可以以其他用户来运行 Confluence. 希望修改用户,打开 ...
- Confluence 6 使用电子邮件可见
Confluence 提供了 3 个电子邮件策略,这些策略 Confluence 管理员可以通过管理员控制台(Administration Console)进行配置: 公开(Public):电子邮件地 ...
- 为 Confluence 6 配置发送邮件消息
如何配置 Confluence 向外发送邮件: 进入 > 基本配置(General Configuration) > 邮件服务器(Mail Servers).这里列出了所有当前配置的 S ...