为了说明白两者,我首先用erase()函数写一个程序,目的是从已经存在的int型容器中删除值为3的元素,代码如下:
#include < vector >
using namespace std;
int main()
{
vector<int> ivec;
int i;
vector<int>::iterator it;
for(i = 0;i < 10;++i)
ivec.push_back(i);
for(i = 0;i < 10;++i)
ivec.push_back(i);
for(it = ivec.begin();it != ivec.end();++it)
if(*it == 3)
ivec.erase(it); //此处执行的是删除操作
for(it = ivec.begin();it != ivec.end();++it)
cout<<*it<<endl;
return 0;
}
但最终的结果闭并不是我所想要的,出现了如下错误:
不用多想,就应该能猜出错误的根源,因为erase()操作会使后面的迭代器失效,当删除掉第一个值为3的元素后,后面的迭代器跟之前的迭代器不同了,如果还是在以前迭代器的基础上进行++操作的话,就会出现上面的问题,在C++ Primer中的9.2.2节也提到了这一点,使用erase()操作后,任何指向已删除元素的迭代器都具有无效值,毕竟该迭代器指向了容器中不再存在的元素。
如果想比较保险的删除容器中的一个元素的话,还是推荐使用泛型算法remove_if()好了,首先需要指出的是,泛型算法不依赖于特定的容器类型,它是“泛型”的,可作用在不同类型的容器和不同类型的元素上。此外,还有这些算法从不使用容器操作,因而其实现和类型无关,元素的访问和遍历都是通过迭代器实现的,泛型算法可能会改变存储在容器中的元素的值,也许会在容器中移动元素,但是,算法从不直接添加或者删除元素。
首先介绍下msdn中对remove_if()的介绍:
算法的功能是:Eliminates elements that satisfy a predicate from a given range without disturbing the order of the remaining elements and returning the end of a new range free of the specified value.
翻译过来就是说:在一个给定范围内删除满足一定条件的元素,在删除元素的过程中不改变剩余元素的位置,并同时返回一个没有要删除元素的新容器的迭代器end值。
我们可以利用这个remove_if()的返回值来删除剩余的元素,这个只需要加入语句ivec.erase(remove_if(****),ivec.end());就可以了。
用remove()和remove_if()其实都可以很简单的解决在上个程序中要解决的问题,remove()的返回值跟remove_if()的返回值是一样的,程序如下:
#include < vector >
#include < algorithm >
using namespace std;
// bool compare(int d)
// {
// return d == 3;
// }
int main()
{
vector<int> ivec;
int i;
vector<int>::iterator it;
for(i = 0;i < 5;++i)
ivec.push_back(i);
for(i = 0;i < 5;++i)
ivec.push_back(i);
//it = remove_if(ivec.begin(),ivec.end(),compare);
it = remove(ivec.begin(),ivec.end(),3);
ivec.erase(it,ivec.end());
for(vector<int>::iterator it = ivec.begin();it != ivec.end();++it)
cout<<*it<<endl;
return 0;
}
刚才看到Effective C++中有关于这方面的知识,第32条条款讲到了删除元素的知识,可以去看下,这里就不再赘述了。