32. 如果确实需要删除元素,则需要在remove这一类算法之后调用erase

从容器中删除元素,唯一的办法是调用容器的成员函数,几乎总是erase的某种形式。因为从容器中删除元素的唯一方法是调用容器的成员函数,而remove算法并不知道它操作的元素所在的容器,所以remove不可能从容器中删除元素。使用remove算法从容器中删除元素,容器中的元素不会因此而减少。

remove算法不是真正意义上的删除,因为它做不到。

remove算法移动了区间中的元素,“不用被删除”的元素已到了区间的前部(保存原来的相对顺序)。它返回一个迭代器指向最后一个"不用被删除"的元素之后的元素。这个返回值相当于该区间的"新的逻辑结尾"。

从容器中删除元素的正确方法:

序列容器(以vector为例):

std::vector<int> datas;
...初始化datas
int destData = 10;
...
datas.erase(std::remove(datas.begin(), datas.end(), destData), datas.end());  

list:

std::list<int> datas;
...初始化datas
int destData = 10;
...
datas.remove(10); 

关联容器(以map为例):

std::map<int, int> datas;
...初始化datas
datas.erase(10);

需要注意的是:
list中的remove是真正可以将被删除元素从容器中删除的,等同于调用了erase-remove方法。
和remove算法类似的算法还有remove_if和unique,它们都是将不需要的元素放入容器的后面,然后返回一个迭代器。
同时针对它们,list中也有相应的成员函数remove_if和unique。它们都会将不需要的元素删除掉。

下面是SGL STL中remove算法的源码:

// 将不等于目标值的元素依次赋值给_result
template <class _InputIter, class _OutputIter, class _Tp>
_OutputIter remove_copy(_InputIter __first, _InputIter __last, _OutputIter __result, const _Tp& __value)
{
	__STL_REQUIRES(_InputIter, _InputIterator);
	__STL_REQUIRES(_OutputIter, _OutputIterator);
	__STL_REQUIRES_BINARY_OP(_OP_EQUAL, bool, typename iterator_traits<_InputIter>::value_type, _Tp);
	for (; __first != __last; ++__first)
		if (!(*__first == __value))
		{
			*__result = *__first;
			++__result;
		}

	return __result;
}

template <class _ForwardIter, class _Tp>
_ForwardIter remove(_ForwardIter __first, _ForwardIter __last, const _Tp& __value) {
	__STL_REQUIRES(_ForwardIter, _Mutable_ForwardIterator);
	__STL_REQUIRES_BINARY_OP(_OP_EQUAL, bool, typename iterator_traits<_ForwardIter>::value_type, _Tp);
	__STL_CONVERTIBLE(_Tp, typename iterator_traits<_ForwardIter>::value_type);
	__first = find(__first, __last, __value); // 找到第一个等于目标值的位置
	_ForwardIter __i = __first;
	// 如果容器中没有目标值,直接返回容器的起始地址;否则从第一个目标值位置的下一个元素开始执行remove_copy
	return __first == __last ? __first : remove_copy(++__i, __last, __first, __value);
}

算法示例:

使用一个实际例子来分解remove算法,容器中的元素为 1 2 3 4 3 5,删除的元素为3,下面是每一步的分解:

1 2 3® 4(f) 3 5:__result指向3,__first指向4,将4赋值给3,序列变为:1 2 4 4 3 5
1 2 4 4® 3 5(f):__result指向第二个4, __first指向5, 将5赋值4,序列变为 :1 2 4 5 3 5
1 2 4 5 3® 5:__result指向3,__first指向容器end(),算法结束,返回__result指向3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值