开发者社区> 技术小美> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

[C++再学习系列] STL容器删除操作总结

简介:
+关注继续查看

由于容器所对应不同的迭代器、指针和引用的失效规则 ,使得容器的删除操作较为复杂。解决问题的最好方法取决于你是怎样鉴别出哪个对象是要被去掉的,储存它们的容器的类型,和当你删除它们的时候你还想要做什么(如果有的话)。为此分 3 种情况讨论:

去除一个容器中有特定值的所有对象:

 1) 如果容器是 vector 、 string 或 deque ,使用 erase-remove 惯用法。

2) 如果容器是 list ,使用 list::remove 。

3) 如果容器是标准关联容器,使用它的 erase 成员函数。 

示例:

Container<int> c;  // 去除值为 1963 的元素

c.erase(remove(c.begin(), c.end(), 1963), c.end()); // 当 c 是 vector 、 string 或 deque 时, erase-remove 惯用法是去除特定值的元素的最佳方法

c.remove(1963);     // 当 c 是 list 时, remove 成员函数是去除特定值的元素的最佳方法

c.erase(1963);        // 当 c 为关联容器

去除一个容器中满足一个特定判定式的所有对象:

1) 如果容器是 vector 、 string 或 deque ,使用 erase-remove_if 惯用法。

2) 如果容器是 list ,使用 list::remove_if 。

3) 如果容器是标准关联容器,使用 remove_copy_if 和 swap( 使用临时容器 ) ,或写一个循环来遍历容器元素,当你把迭代器传给 erase 时记得后置递增它。 

示例:特定判断式 : bool badValue(int x);   // 返回 x 是否是“ bad ”

c.erase(remove_if(c.begin(), c.end(), badValue),  c.end()); // 当 c 是 vector 、 string 或 deque

c.remove_if(badValue);     // 当 c 是 list 时

// 关联容器的删除 使用  后置递增传给 erase 的迭代器  技术

AssocContainer<int> c;

for (AssocContainer<int>::iterator i = c.begin();  // for 循环的第三部分是空的

       i != c.end();  /*nothing*/ ){        // 循环体控制 i 递增

       if (badValue(*i)) {

c.erase(i++);   // 删除 i ,副作用 i 递增

    // logFile << "Erasing " << *i <<'\n';    // 写日志文件 ,or other operators

       }

       else ++i;         // 递增

}

说明:为什么要使用后置递增?后置递增会增加临时副本,效率低。但此处一定要使用后置递增。关联容器的 erase 并不返回删除后的下一个有效迭代器,同时删除后的迭代器是无效迭代器。 为达到删除单前迭代器同时指向后一个迭代器,我们必须在删除前递增迭代器,同时记录当前迭代器并删除。后置递增操作除增加迭代器外,同时返回递增前的对象拷贝,完全满足所需的删除条件。  

在循环内做某些事情并删除对象:

1) 如果容器是标准序列容器,写一个循环来遍历容器元素,每当调用erase时记得都用它的返回值更新你的迭代器。

2) 如果容器是标准关联容器,写一个循环来遍历容器元素,当把迭代器传给erase时记得后置递增它(例子同上) 。 

示例:标准序列容器 ( 标准关联容器,同上 )

for (SeqContainer<int>::iterator i = c.begin();

       i != c.end();){

       if (badValue(*i)){

              logFile << "Erasing " << *i << '\n';

              i = c.erase(i);         // 通过把 erase 的返回值获取有效的迭代器

       }                                

       else

              ++i;

}

说明:对序列容器为什么不使用  后置递增你要传给 erase 的迭代器  技术?原因在于 vector 、 string 和 deque 容器调用erase 后,不仅使所有指向被删元素的迭代器失效,也使被删元素之后 的所有迭代器失效 ( 可能重新分配地址空间 ) 。为了使序列容器的 erase 后,能获得删除后的有效迭代器,其 erase 将迭代器作为返回值:一旦删除完成, erase 返回指向紧接在被删元素之后的元素的有效迭代器。

注意: list 虽是序列容器,但采用节点存储方式,故不存在地址重新分配。因此可以像 vector/string/deque 一样或像关联容器一样对待 list ;两种方法都可以为 list 工作。

---------------------------------------------------

兄弟的公司:立即购--手机购物,诚信网购

兄弟的公司:立即团

欢迎转载,请注明作者和出处

本文转自 zhenjing 博客园博客,原文链接:http://www.cnblogs.com/zhenjing/archive/2011/01/30/STL_remove.html   ,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
全方位解读服务网格(Service Mesh)的背景和概念
为了解决微服务框架的侵入性问题,我们引入服务网格。
1212 0
PolarDB 并行查询的前世今生
本文会深入介绍PolarDB MySQL在并行查询这一企业级查询加速特性上做的技术探索、形态演进和相关组件的实现原理,所涉及功能随PolarDB MySQL 8.0.2版本上线。
478 0
企业内部应用接入钉钉获取部门及人员信息
企业内部应用接入钉钉,同时通过API获取当前企业下部门及人员信息
1161 0
MySQL模糊查询再也用不着 like+% 了!
我们都知道 InnoDB 在模糊查询数据时使用 "%xx" 会导致索引失效,但有时需求就是如此,类似这样的需求还有很多,例如,搜索引擎需要根基用户数据的关键字进行全文查找,电子商务网站需要根据用户的查询条件,在可能需要在商品的详细介绍中进行查找,这些都不是B+树索引能很好完成的工作。 通过数值比较,范围过滤等就可以完成绝大多数我们需要的查询了。但是,如果希望通过关键字的匹配来进行查询过滤,那么就需要基于相似度的查询,而不是原来的精确数值比较,全文索引就是为这种场景设计的。
25665 0
阿里云云原生一体化数仓正式发布  助力企业数据驱动业务创新
云原生一体化数仓是集阿里云大数据产品MaxCompute、DataWorks、Hologres三种产品能力于一体的一站式大数据处理平台。核心是3个一体化和全链路数据治理能力,包括离线实时一体、湖仓一体、分析服务一体、全链路数据治理。
1589 0
全面公测|Grafana服务:一张图表胜过千行指标&日志
Grafana 帮助运维人员轻松处理各类运维过程中遇到的各类数据可视化与分析难题。目前阿里云 Grafana 服务全面免费公测,帮助企业轻松构建运维数据可视化平台,轻松实现数据驱动运维!
1135 0
一起学Golang系列(五)初次接触Go语言可能遇到的各种坑!
前面介绍了Go语言的基础语法,所谓磨刀不误砍柴工,希望大家还是能熟悉掌握这些基础知识,这样后面真正学起Go来才会得心应手。 作为初学者。Go语言的语法有些和java类似,但也有很多不一样的地方。刚开始都会遇到各种各样的坑。下面就来总结下学习go语言的过程中,遇到的各种坑。
997 0
设备接入--海康摄像头SDK
springboot-对接海康摄像头,兼容window和Linux环境
1317 0
Flink SQL 在快手的扩展和实践
快手实时计算团队技术专家张静、张芒在 FFA 2021 的分享
1127 0
无影云桌面,企业与个人的应用神器
阿里云无影云桌面( Elastic Desktop Service)的原产品名为弹性云桌面,融合了无影产品技术后更名升级。它可以为您提供易用、安全、高效的云上桌面服务,帮助您快速构建、高效管理桌面办公环境,提供安全、灵活的办公体系。
276273 0
+关注
6819
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载