C++ STL 中 remove 和 erase 的区别

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ STL 中 remove 和 erase 的区别相关的知识,希望对你有一定的参考价值。

vector中的remove的作用是将等于value的元素放到vector的尾部,但并不减少vector的size
vector中erase的作用是删除掉某个位置position或一段区域(begin, end)中的元素,减少其size

list容器中的remove 成员函数,原型是void remove (const value_type& val);
他的作用是删除list中值与val相同的节点,释放该节点的资源。

而list容器中的erase成员函数,原型是iterator erase (iterator position);
作用是删除position位置的节点。这也是与remove不同的地方。
考虑到list::erase是与位置有关,故erase还存在API: iterator erase (iterator first, iterator last);

对于set来说,只有erase API,没有remove API。 erase 的作用是把符合要求的元素都删掉。
(1) void erase (iterator position);
(2) size_type erase (const value_type& val);
(3) void erase (iterator first, iterator last);

综上所述,erase一般是要释放资源,真正删除元素的,
而remove主要用在vector中,用于将不符合要求的元素移到容器尾部,而并不删除不符合要求的元素
原文链接:http://hi.baidu.com/tkzlpocleodtxzr/item/3a3a6037fdc8460cceb9fe86
vector中erase是真正删除了元素, 迭代器访问不到了。 algorithm中的remove只是简单的把要remove的元素移到了容器最后面,然后其余元素前移,迭代器还是可以访问到的。因为algorithm通过迭代器操作,不知道容器的内部结构,所以无法做到真正删除。
remove并不真正从容器中删除元素(容器大小并未改变),而是将每一个与value不相等的元素轮番赋值给first之后的空间,返回值FowardIterator 标示出重新整理后的最后元素的下一个位置。所以可以有以下操作:
vector<int> array;
array.erase(remove(array.begin(),array.end(),6),array.end());
删除数组中所有元素等于6的元素

原文链接:http://www.cnblogs.com/painful/archive/2011/08/16/2140704.html
C++的STL通过iterator将container和algorithm分离,并通过functor提供高可定制性。iterator可以看作是一种契约,algorithm对iterator进行操作,algorithm很难对container进行直接操作,这是因为algorithm对container所知甚少,一段代码,若未利用操作对象所知全部信息,将难以达到性能之极,并伴随其它种种折中现象。当然,这种“未知性”是必须的——algorithm对于真正的操作对象container不能做出太多假设,若假设过多,何来一个algorithm可以作用若干不同container的妙举,STL强大威力也将受损不少。
啰嗦几句,开个小头,转入正题。 先给出几个关于STL中erase和remove(remove_if等,下称remove类函数)的事实,小小复习:
erase一般作为一个container的成员函数,是真正删除的元素,是物理上的删除
作为算法部分的remove类函数,是逻辑上的删除,将被删除的元素移动到容器末尾,然后返回新的末尾,此时容器的size不变化
部分容器提供remove类成员函数,那么代表的是真正物理意义上的删除元素
如果该容器是vector、string或者deque,使用erase-remove idiom或者erase-remove_if idiom
如果该容器是list,使用list::remove或者list:remove_if成员函数
如果该容器是一个associative container,使用asso_con::erase成员函数或者remove_copy_if结合swap等方式
有一些比较特殊的容器具现,比如vector<bool>等,暂不考虑。
参考技术A C++ STL中的remove和erase函数曾经让我迷惑,同样都是删除,两者有什么区别呢?

vector中的remove的作用是将等于value的元素放到vector的尾部,但并不减少vector的size

vector中erase的作用是删除掉某个位置position或一段区域(begin, end)中的元素,减少其size

list容器中的remove 成员函数,原型是void remove (const value_type& val);

他的作用是删除list中值与val相同的节点,释放该节点的资源。

而list容器中的erase成员函数,原型是iterator erase (iterator position);

作用是删除position位置的节点。这也是与remove不同的地方。

考虑到list::erase是与位置有关,故erase还存在API: iterator erase (iterator first, iterator last);

对于set来说,只有erase API,没有remove API。 erase 的作用是把符合要求的元素都删掉。

(1) void erase (iterator position);
(2) size_type erase (const value_type& val);
(3) void erase (iterator first, iterator last);

综上所述,erase一般是要释放资源,真正删除元素的,

而remove主要用在vector中,用于将不符合要求的元素移到容器尾部,而并不删除不符合要求的元素。

STL函数——remove函数

1. remove函数

remove是STL中的函数,和erase是有区别的:

(1)erase是容器自带的成员函数,而remove是STL中的函数;

(2)erase是真正的删除,而remove是虚假的删除。(下面会说明)

作用

顾名思义,该函数作用是移除容器中的元素。

参数

参数有三个:
头指针、尾指针和要删除的元素。

int b[] = {1,2,3,4,5,5,6};
vector<int> a(b, b+7);
vector<int>::iterator it1 = remove(a.begin(), a.end(), 5);

返回值

remove返回值为一迭代器,指向删除后的真正结尾。(之后会解释)

2. 错误用法

int b[] = {1,2,3,99,5,99,7,8,9,99};
vector<int> a(b, b+10);
vector<int>::iterator it;
for(it=a.begin(); it!=a.end(); it++)
    cout<<*it<<" ";
cout<<endl;
remove(a.begin(), a.end(), 99);
for(it=a.begin(); it!=a.end(); it++)
    cout<<*it<<" ";
//我们期望的输出:1 2 3 5 7 8 9

我们看实际输出的结果是什么:
在这里插入图片描述
并不是我们想的那样,为什么?

3.remove的执行过程

remove函数并不会“真正地”对特定元素进行删除,它只会移动指定区间中的元素直到所有“不删除的”元素在区间的开头(相对位置不变),并返回此时的newEnd迭代器,newEnd后的元素值保持不变。

示意图:
remove前:
在这里插入图片描述
remove后:
在这里插入图片描述
所以我们说,remove只是虚假的删除,因为容器的size并没有变。

【举例】

int b[] = {1,2,3,99,5,99,7,8,9,99};
vector<int> a(b, b+10);
vector<int>::iterator it;
for(it=a.begin(); it!=a.end(); it++)
    cout<<*it<<" ";
cout<<endl;
vector<int>::iterator newEnd = remove(a.begin(), a.end(), 99);
for(it=a.begin(); it!=newEnd; it++)
    cout<<*it<<" ";
cout<<endl<<a.size();

在这里插入图片描述

4. 如何真正删除

搭配容器自带的erase函数,即可真正删除
【举例】

int b[] = {1,2,3,99,5,99,7,8,9,99};
vector<int> a(b, b+10);
vector<int>::iterator it;
for(it=a.begin(); it!=a.end(); it++)
    cout<<*it<<" ";
cout<<endl;
vector<int>::iterator newEnd = remove(a.begin(), a.end(), 99);
a.erase(newEnd, a.end());
for(it=a.begin(); it!=a.end(); it++)
    cout<<*it<<" ";
cout<<endl<<a.size();

在这里插入图片描述
值得注意的是,list自带有remove成员函数(vector等容器没有),用法和erase+remove相同,且效率更高:
【举例】

list<int> l = {1,2,3,99,5,99,7,8,9,99};
l.remove(99);
for(list<int>::iterator it=l.begin(); it!=l.end(); it++)
    cout<<*it<<" ";
cout<<endl<<l.size();

在这里插入图片描述

以上是关于C++ STL 中 remove 和 erase 的区别的主要内容,如果未能解决你的问题,请参考以下文章

C++ STL 中 remove 和 erase 的区别

STL函数——remove函数

STL之vector的erase函数和遍历

C++ STL中erase函数的用法 求助~~

C++ STL中erase函数的用法 求助~~

C++中stl模版中的erase()和end()(和我之前提的问题不一样)