关于C++11 stl中remove函数的讨论

关于C++11 stl中remove函数的讨论

直接上代码:

#include <algorithm>
#include <iterator>
#include <list>
#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> vec = {1,2,3,3,4,5,6};
 
    
    // print all elements of the collection
    cout<<"pre:";
    for(auto it=vec.cbegin();it!=vec.cend();++it){
        cout<<*it<<" ";
    }
    cout<<endl;
    cout<<vec.size()<<endl;

    // remove all elements with value 3
    remove(vec.begin(),vec.end(),3);

    // print all elements of the collection
    cout<<"post:";
    for(auto it=vec.cbegin();it!=vec.cend();++it){
        cout<<*it<<" ";
    }
    cout<<endl;
    
    cout<<vec.size()<<endl;

    return 0;
}

输出结果:

pre: 1 2 4 5 6 5 6
7
post:1 2 4 5 6 5 6
7

由于对STL缺乏深层认识,我们一般认为调用remove()后,输出结果应该是:12456

但我们看到这样的话,vector大小变成7。然而调用remove后,前后并不改变vector的大小。

remove()并没有改变集合中的元素数量。cend()返回的是当初那个终点,size()返回的还是当初那个大小。元素次序改变了,有些元素被删除了,值为3的元素被其后的元素覆盖了。

接下来,思考为什么会出现这种情况呢?

先看一段代码:

#include <algorithm>
#include <iterator>
#include <iostream>
#include <vector>
using namespace std;

int main()
{
 	vector<int> vec = {1,2,3,3,4,5,6};
    vector<int>::iterator end = remove(vec.begin(),vec.end(),3);
    
    //输出vector元素
    for(auto it=vec.cbegin();it!=vec.cend();++it){
        cout<<*it<<" ";
    }
    cout<<endl;

    cout<<vec.size()<<endl;
    cout<<"--------"<<endl;

    
    for(auto it=vec.cbegin();it!=end;++it){
        cout<<*it<<" ";
    }
    cout<<endl;

    cout<<vec.size()<<endl;
    cout<<"--------"<<endl;
	
    //计算删除的元素个数,即两个迭代器位置的距离
    cout<<"number of removed elements: "
        <<distance(end,vec.end())<<endl;
   
    return 0;
}

输出结果:

1 2 4 5 6 5 6

7

1 2 4 5 6

7

number of removed elements: 2

看了这段代码,大概就明白了,原来remove()函数返回的是end,即这个end正是“被修改集合”经过元素移除动作后的新的逻辑终点,而cend迭代器还是当初那个终点。

remvove()会把原本置于后面的没有移除的元素向前移动,覆盖被移除的元素。而未被移除的元素在相对次序上保持不变。调用者在调用此算法后,逻辑起点还是原来的begin,而逻辑终点是返回的新逻辑终点,而不是原来的终点end。

另外一种情况:

如果remove删除的是vector最后一个元素呢,出现什么情况?

#include <algorithm>
#include <iterator>
#include <list>
#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> vec = {1,2,3,3,4,5,6};

    
    // print all elements of the collection
    cout<<"pre:";
    for(auto it=vec.cbegin();it!=vec.cend();++it){
        cout<<*it<<" ";
    }
    cout<<endl;
    cout<<vec.size()<<endl;

    // remove all elements with value 3
    remove(vec.begin(),vec.end(),6);

    // print all elements of the collection
    cout<<"post:";
    for(auto it=vec.cbegin();it!=vec.cend();++it){
        cout<<*it<<" ";
    }
    cout<<endl;
    
    cout<<vec.size()<<endl;

    return 0;
}

输出结果:

pre:1 2 3 3 4 5 6
7
post:1 2 3 3 4 5 6
7

可以看到调用remove()的前后结果是一样的。

解释:remvove()会把原本置于后面的没有移除的元素向前移动,覆盖被移除的元素。由于删除6是最后一个元素,而6下一个元素没有值,就覆盖不了需要被删除的元素6,因此这个需要被删除的6并没有真正被删除掉,vector还保持原样。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值