posts - 311, comments - 0, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理
为了说明白两者,我首先用erase()函数写一个程序,目的是从已经存在的int型容器中删除值为3的元素,代码如下:
#include <iostream>
#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 <iostream>
#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条条款讲到了删除元素的知识,可以去看下,这里就不再赘述了。