[C++]顺序容器和关联容器的删除

概述

一个合格的容器(Container)必须支持增删改查,C++的顺序容器和关联容器也不例外。
不同于insert和search,erase操作涉及到多种情况,尤其是和迭代器相结合的时候。
本文总结常用C++常用容器的erase的正确做法。

  • 顺序容器:vector,dequeue,list,string
  • 关联容器:set,map,unordered_set, unordered_map

顺序容器

vector

vector是STL中唯一一个保证内存连续的容器,也是我们最常用的容器。

删除值为val的元素
void EraseVec()
{
    std::vector<int> vec{ 1, 2, 3, 4, 5, 5, 6, 7 };
    vec.erase(std::remove(vec.begin(), vec.end(), 5), vec.end());
}

上述代码是最标准的在vector中删除值为5的元素的方法,你会发现有两个很容易让人产生误会的接口:
erase和remove,我们看一下他们的原型:

iterator erase (iterator begin, iterator end);  
//tips : 删除容器中迭代器在[first; last)范围内的元素
//return : 最后一个被删除的元素的下一个元素的迭代器
iterator remove(iterator begin, iterator end, val);
//tips : 移除容器中迭代器在[first; last)范围内的值为val的元素
//return : 被成功移除的之后,剩余的有效元素的下一个元素的迭代器

我们可以看到,remove做的操作是移除而erase是删除,这两者到底有什么区别呢?
我们刚创建的vec的内存布局如下:

这里写图片描述

在remove(begin,end,5)之后,内存布局如下:
这里写图片描述

它仅仅做了移除操作,把不要的元素放在了末尾(这是其中一种实现,你不能对67后面的两个位置的值做出任何假设),但是capacity甚至size都没有改变,也就是说元素并没有被删除。
更可怕的是,如果你做了下列操作:

std::remove(vec.begin(), vec.end(), 5);
for (auto it = vec.begin(); it != vec.end(); ++it)
{
    printf("%d\n", *it);
}

你会发现输出的值是12346755(或者可能是132456767),元素根本没有被删除
vec.erase(std::find(vec.begin(), vec.end(), 5))

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值