C++之erase、remove 、remove_if的区别

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<int> v = { 4, 3, 2, 5, 5, 5, 5, 4, 3 };
	vector<int>::iterator it;
	for (it = v.begin(); it < v.end(); ++it)
	{
		if (*it == 5)
		{
			v.erase(it);
		}
	}
}

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

void test()
{
	vector<int> v = { 4, 3, 2, 5, 5, 5, 5, 4, 3 };
	vector<int>::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 <class ForwardIterator, class T>
 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<char> v;
	vector<char>::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<char> v;
	vector<char>::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<int> 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<int> 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<int> 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);
}

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

  • 16
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
这三个函数是 STL 算法中用于删除元素的函数。它们的作用分别是: - `remove_if`:删除满足指定条件的元素,返回指向新的逻辑结尾的迭代器。 - `remove_copy`:将满足指定条件的元素拷贝到另一个容器中,返回指向新的逻辑结尾的迭代器。 - `remove_copy_if`:将不满足指定条件的元素拷贝到另一个容器中,返回指向新的逻辑结尾的迭代器。 下面是它们的用法和示例: ```cpp #include <iostream> #include <algorithm> #include <vector> using namespace std; int main() { // remove_if vector<int> v1{1, 2, 3, 4, 5}; auto it1 = remove_if(v1.begin(), v1.end(), [](int x) { return x % 2 == 0; }); v1.erase(it1, v1.end()); for (int x : v1) { cout << x << " "; // 输出 1 3 5 } cout << endl; // remove_copy vector<int> v2{1, 2, 3, 4, 5}; vector<int> v3; remove_copy(v2.begin(), v2.end(), back_inserter(v3), [](int x) { return x % 2 == 0; }); for (int x : v3) { cout << x << " "; // 输出 1 3 5 } cout << endl; // remove_copy_if vector<int> v4{1, 2, 3, 4, 5}; vector<int> v5; remove_copy_if(v4.begin(), v4.end(), back_inserter(v5), [](int x) { return x % 2 == 0; }); for (int x : v5) { cout << x << " "; // 输出 1 3 5 } cout << endl; return 0; } ``` 注意,这三个函数并不真正删除容器中的元素,而是返回指向新的逻辑结尾的迭代器。如果要真正删除元素,需要结合容器的 `erase` 函数使用。此外,`remove_copy` 和 `remove_copy_if` 会将满足条件的元素拷贝到另一个容器中,因此要注意目标容器的类型和大小。在示例中,使用了 `back_inserter` 函数将元素插入 `vector` 的尾部。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值