慎重选择删除元素的方法
2015-10-13 13:46
148 查看
一、要删除容器中中有特定值的所有对象:
(1)如果容器是vector、string或deque,则使用erase-remove习惯用法:
(2)如果容器是list,则使用list::remove,此时remove是其成员函数:
(3)如果容器是一个标准关联容器,则使用它的erase成员函数,不能使用remove函数,因为关联容器不含有remove函数:
二、要删除容器中满足特定判别条件的所有对象:
删除判使bool badValue(int);返回true的每一个对象
(1)如果容器是vector、list或deque,则使用erase-remove_if习惯用法:
(2)如果容器是list,则使用list::remove_if:
(3)如果容器是标准关联容器
方法一:简单但效率稍低,利用remove_copy_if函数把我们需要的值赋值到另外一个容器中,然后用swap交换这两个容器的内容
方法二:关联容器没有提供类似remove_if的成员函数,则需要写一个循环遍历c中的元素,并个遍历过程中删除元素
假设我们这么写
当容器内的一个元素被删除之时,指向该元素的所有迭代器都将变得无效,一旦c.erase(i)返回后,i就成为无效值,对于这个循环,那么i++肯定失效;
正确的方法
这样,我们把旧的i传给erase,但在erase开始执行前也递增了i
三、在删除每次元素时,都向日志文件写一条信息:
(1)对于关联容器十分简单,仅只需做一点点修改
如果容器是一个标准序列容器,我们不能再用erase_remove_if的习惯用法。且不能使用刚刚关联容器的循环设计,因为对于序列容器,调用erase不仅会使指向被删除元素的迭代器无效,也会使被删除元素之后的所有迭代器失效,因此采用++i、i++都无济于事。
(2)对于序列容器,我们需要采取不同的策略,尤其要利用其返回值。一旦erase完成,它是指向紧随被删除元素的下一个元素的所有迭代器,则写一个循环来遍历容器中的元素,记住每次调用erase时,要用它的返回值更新迭代器。
(3)对于list容器一般采用和vector、string、deque相同的方式
参考:Effective Stl
(1)如果容器是vector、string或deque,则使用erase-remove习惯用法:
c.erase(remove(c.begin(),c.end(),1963),c.end());
(2)如果容器是list,则使用list::remove,此时remove是其成员函数:
c.remove(1963);
(3)如果容器是一个标准关联容器,则使用它的erase成员函数,不能使用remove函数,因为关联容器不含有remove函数:
c.erase(1963);
二、要删除容器中满足特定判别条件的所有对象:
删除判使bool badValue(int);返回true的每一个对象
(1)如果容器是vector、list或deque,则使用erase-remove_if习惯用法:
c.erase(remove_if(c.begin(),c.end(),badValue),c.end());
(2)如果容器是list,则使用list::remove_if:
c.remove_if(c.begin(),c.end(),badValue);
(3)如果容器是标准关联容器
方法一:简单但效率稍低,利用remove_copy_if函数把我们需要的值赋值到另外一个容器中,然后用swap交换这两个容器的内容
Container<int> c;//c现在是一个关联容器 Container<int> goodValues;//保存不被删除值的临时容器 remove_copy_if(c.begin(),c.end(),inserter(goodValues,goodValues.end()),badValue);//把不被删除的值从c复制到goodValues中 c.swap(goodValues);//交换c和goodValues的内容
方法二:关联容器没有提供类似remove_if的成员函数,则需要写一个循环遍历c中的元素,并个遍历过程中删除元素
假设我们这么写
//错误写法 for(Container<int>::iterator i=c.begin();i!=c.end();++i) { if(badValue(*i)) c.erase(i);//迭代器失效 }
当容器内的一个元素被删除之时,指向该元素的所有迭代器都将变得无效,一旦c.erase(i)返回后,i就成为无效值,对于这个循环,那么i++肯定失效;
正确的方法
for(Container<int>::iterator i=c.begin();i!=c.end();) {//for循环第三部分是空的 if(badValue(*i)) c.erase(i++);// else ++i; }
这样,我们把旧的i传给erase,但在erase开始执行前也递增了i
三、在删除每次元素时,都向日志文件写一条信息:
(1)对于关联容器十分简单,仅只需做一点点修改
ofstream logFile;//要写入的日志文件 Container<int> c; for(Container<int>::iterator i=c.begin();i!=c.end();)//同上 { if(badValue(*i)) { logFile<<"Erasing"<<*i<<'\n';//写入日志文件 c.erase(i++);//删除元素 } else { ++i; } }
如果容器是一个标准序列容器,我们不能再用erase_remove_if的习惯用法。且不能使用刚刚关联容器的循环设计,因为对于序列容器,调用erase不仅会使指向被删除元素的迭代器无效,也会使被删除元素之后的所有迭代器失效,因此采用++i、i++都无济于事。
(2)对于序列容器,我们需要采取不同的策略,尤其要利用其返回值。一旦erase完成,它是指向紧随被删除元素的下一个元素的所有迭代器,则写一个循环来遍历容器中的元素,记住每次调用erase时,要用它的返回值更新迭代器。
for(Container<int>::iterator i=c.begin();i!=c.end();) { if(badValue(*i)) { LogFile<<"Erasing"<<*i<<'\n'; i=c.erase(i); }else { ++i; } }
(3)对于list容器一般采用和vector、string、deque相同的方式
参考:Effective Stl
相关文章推荐
- set,env和export这三个命令的区别
- 最值得阅读学习的 10 个 C 语言开源项目代码
- 基于阿里云的移动客户端服务器架构图
- [转]卡西欧手表调日期正确方法
- Quartz.NET总结(一)入门
- Cg shading in world space
- ocp-368
- ocp-367
- ocp-366
- 【解决】kettle启动时出现的Java Runtime Environment异常
- 自动化挂载HDFS文件系统到本地目录
- JavaScript性能优化小知识总结
- 微信红包API接口(PHP)
- 转:运行yum报错Error: Cannot retrieve metalink for reposit
- HTML 样式-CSS
- “error C3867: “XXX”: 函数调用缺少参数列表;请使用“&XXX”创建指向成员的指针”的错误
- iOS9 HTTP 不能正常使用的解决办法
- 尝试C++神经网络类库FANN
- Cg shader with all built-in vertex input parameters
- ocp-365