令人疑惑的 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)更少的内存分配 在区间 ...
随机推荐
- ffmpeg 加载双语字幕
set infile=in.mp4 set subfile1=cn.srt set subfile2=en.srt set subvf1="subtitles=%subfile1%:forc ...
- Laravel 5.2--改变数据库字段值,编辑时候,默认选中
模型 <?php namespace App\Models; use App\Helpers\ImageHelper; use App\Libraries\Nestedset\NodeTrait ...
- PKUWC2019垫底记
凭着noip2018中超凡的运气,我来到了纪中. DAY0 听说PKUWC可以看榜?那就不用担心写挂啦!开心! 刚从雅礼回来休息了一天,下午就和hz一起坐上教练的车去到了中山纪中. 纪中好大好漂亮啊! ...
- Poco::Crypto--加解密(AES)
Poco::Crypto--加解密(AES) 1 int main(const std::vector<std::string>& args) 2 { 3 /*TO DO*/ 4 ...
- 经典JS闭包面试题(来理解闭包)(转)
转载地址:http://www.cnblogs.com/xxcanghai/p/4991870.html 先看代码: function fun(n,o) { console.log(o) return ...
- OC Swift中检查代码行数
1 打开终端 cd 进去当前项目 2 总行数查看命令 find . -name "*.m" -or -name "*.h" | xargs wc -l ...
- python之vscode中手动选择python解释器(mac)
要选择特定的解释器,请从命令选项板(⇧⌘P)调用Python:Select Interpreter命令. 更详细请看:http://www.cnblogs.com/it-tsz/p/9312151.h ...
- flask 面试题
1,什么是Flask,有什么优点?概念解释Flask是一个Web框架,就是提供一个工具,库和技术来允许你构建一个Web应用程序.这个Web应用程序可以是一些Web页面,博客,wiki,基于Web的日里 ...
- Hive shell 基本命令
首先连接 hive shell 直接输入 hive启动, 使用--开头的字符串来表示注释 hive>quit; --退出hive hive> exit; --exit会影响之前的使用,所以 ...
- 反向找related_name以及limit_fields_to
问题2:客户的添加页面,通过popup创建用户时 解决方案: 如果新创建的用户时:如果是销售部的人,页面才增加 目的是:拿到limit_choices_to,就可以判断了 当有两个Foreignkey ...