博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++之erase、remove 、remove_if的区别
阅读量:2243 次
发布时间:2019-05-09

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

文章目录

erase

作用:删除内存擦除

简单的说,就是能够从内存中擦除掉你想删除的元素

函数原型:

(1)string& erase ( size_t pos = 0, size_t n = npos );
(2)iterator erase ( iterator position );
(3)iterator erase ( iterator first, iterator last );

earse(pos, npos) 删除从pos开始的npos个字符

比如 :earse(1, 3) 删除第二个到第四个字符

void test(){
string s = "Hello World!"; //注意:这里面的参数类型都是size_t,也就是说只能放整数 //如果是 s.earse(s.begin(), 5)将会报错,因为s.begin()的类型不是size_t,而是iterator s.erase(2, 5); //如果没有给出npos,系统会自动删除pos后面的所有元素 s.erase(2);}

结果:

Heorld!
He

erase(position) 删除position位置的元素

void test(){
string s = "Hello World!"; //删除第三个位置的字符 //这个一定要和上面的s.erase(2)区分开,这两者里面的参数类型是不一样的 s.erase(s.begin() + 2); cout << s << endl;}

结果:Helo World!

erase(first, last) 删除从first开始last(不包含last)

void test(){
string s = "Hello World!"; //一定要和s.earse(2, 5)区分开,两者所表示的含义不一样 s.erase(s.begin() + 2, s.end() - 1); cout << s << endl;}

结果:He!

earse所存在的坑

  1. 不能将 s.begin() 强转为int
  2. 当想要删除某一个字符时,需要先找到这个字符(find)
    earse不存在通过字符将其删除的函数
void test(){
string s = "Hello World!"; s.erase(find(s.begin(), s.end(), 'e')); cout << s << endl;}

结果:Hllo World!

  1. 链表容器使用erase删除节点会将下一个元素的地址返回
    例如下面这个题:
    删除所有的5
void test(){
vector
v = {
4, 3, 2, 5, 5, 5, 5, 4, 3 }; vector
::iterator it; for (it = v.begin(); it < v.end(); ++it) {
if (*it == 5) {
v.erase(it); } }}

这个一编译就会报错,因为直接删除会导致迭代器失效(迭代器失效问题会在以后的博客中详细介绍)。因为 it 是个迭代器,可以把它理解为一个指针,把指针删除后(可以理解为野指针),又如何进行 ++ 操作?,故要将删除后的下一个元素位置保存起来。

void test(){
vector
v = {
4, 3, 2, 5, 5, 5, 5, 4, 3 }; vector
::iterator it = v.begin(); while (it != v.end()) {
if (*it == 5) {
//因为erase函数会返回删除元素的下一个元素的地址 it = v.erase(it); } else {
++it; } }}

结果:

在这里插入图片描述

remove

函数原型:

ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val);
简单的说,就是:

remove(first, last, val) 删除first到last之间所有值为val的元素

remove在STL中的源代码

template 
ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val){
ForwardIterator result = first; while (first!=last) {
if (!(*first == val)) {
*result = move(*first); ++result; } ++first; } return result;}

对vector来说

remove只是通过迭代器的指针向后移动来删除,将没有被删除的元素放在链表的前面,并返回一个指向新的位置的迭代器。由于remove()函数不是vector成员函数,因此不能调整vector容器的长度。(对vector来说)remove()函数并不是真正的删除,要想真正删除元素则可以使用erase()或者resize()函数

对于下面的代码:

void test(){
vector
v; vector
::iterator ret; v.push_back('q'); v.push_back('w'); v.push_back('e'); v.push_back('r'); v.push_back('b'); v.push_back('w'); v.push_back('w'); remove(v.begin(), v.end(), 'w');}

结果:

在这里插入图片描述

里面的 ‘w’ 并没有被全部删除,为什么会有这种情况?

在这里插入图片描述

所以,要通过remove删除元素,就要借助earse

void test(){
vector
v; vector
::iterator ret; v.push_back('q'); v.push_back('w'); v.push_back('e'); v.push_back('r'); v.push_back('b'); v.push_back('w'); v.push_back('w'); v.erase(remove(v.begin(), v.end(), 'w'), v.end());}

结果:

在这里插入图片描述

对于list来说

remove()函数作为列表list容器的成员函数,可以从列表容器中删除与x相等的元素,同时会减小列表容器的大小,其减小的数量等于被删除的元素的个数

原型:
remove(const T& val)

void test(){
list
l; l.push_back(1); l.push_back(2); l.push_back(3); l.push_back(3); l.push_back(4); l.push_back(5); l.push_back(3); l.remove(3);}

这次就不用借助erase函数,就可将其全部删除

结果:
在这里插入图片描述

remove_if

函数原型:ForwardIterator remove_if (ForwardIterator first, ForwardIterator last,

UnaryPredicate pred);
简单的说就是:remove_if(first, last, pred) 从first到last中将满足条件pred的元素删除
这个函数就是按条件删除元素

对于vector而言

remove_if的参数是迭代器,通过迭代器无法得到容器本身,而要删除容器内的元素只能通过容器的成员函 数来进行,因此remove系列函数无法真正删除元素,只能把要删除的元素移到容器末尾并返回要被删除元素的迭代器,然后通过erase成员函数来真正删除。

bool IfEqualThree(int ret){
return ret == 3;}void test(){
vector
v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(3); v.push_back(4); v.push_back(5); v.push_back(3); v.erase(remove_if(v.begin(), v.end(), IfEqualThree), v.end());}

结果:

在这里插入图片描述

对于list而言

因为remove_if是list的成员函数,可以直接删除元素

void test(){
list
v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(3); v.push_back(4); v.push_back(5); v.push_back(3); v.remove_if(IfEqualThree);}

结果:

在这里插入图片描述

转载地址:http://ucwdb.baihongyu.com/

你可能感兴趣的文章
sublime text3 快捷键修改
查看>>
关于PHP几点建议
查看>>
硬盘的接口、协议
查看>>
VLAN与子网划分区别
查看>>
Cisco Packet Tracer教程
查看>>
02. 交换机的基本配置和管理
查看>>
03. 交换机的Telnet远程登陆配置
查看>>
微信小程序-调用-腾讯视频-解决方案
查看>>
phpStudy安装yaf扩展
查看>>
密码 加密 加盐 常用操作记录
查看>>
TP 分页后,调用指定页。
查看>>
Oracle数据库中的(+)连接
查看>>
java-oracle中几十个实用的PL/SQL
查看>>
PLSQL常用方法汇总
查看>>
几个基本的 Sql Plus 命令 和 例子
查看>>
PLSQL单行函数和组函数详解
查看>>
Oracle PL/SQL语言初级教程之异常处理
查看>>
Oracle PL/SQL语言初级教程之游标
查看>>
Oracle PL/SQL语言初级教程之操作和控制语言
查看>>
Oracle PL/SQL语言初级教程之过程和函数
查看>>