循环删除容器中元素的方法和陷阱
来源:互联网 发布:淘宝背景音乐怎么添加 编辑:程序博客网 时间:2024/05/29 03:52
算法大师Donald Knuth:不成熟的优化是一切恶果的根源(Permature optimization is the root of all evil )。
STL中的容器主要是两种:序列式容器和关联式容器。
下面讲到的都是我在开发中曾经遇到过的一些问题,有些例子我做了修改,我想初学STL的人基本都会遇到这些问题。
序列式容器:vector list string等等
关联式容器:set map等
1、容器的选择,到底要选什么容器应该根据你的需求和以后的扩展来选,可以参考effective stl上的某个条款,说的很清楚,我就不扯了。
--------------------------------------------------------------------------------
2、怎样正确的删除序列式容器中的数据(循环删除),这里以vevtor为例,至少有两大种方法,STL中任何容器都可以使用迭代器进行元素的遍历,当需要在遍历中删除某些元素时,容器中元素的布局(位置或者排序)会随之改变,当前迭代器所指示的元素也会发生变化,这时继续递增或者递减迭代器进行后续元素的遍历时就要特别小心。容器的元素删除方法很大程度上依赖于操作系统上STL的实现版本,不同的系统和STL版本均有不同的定义,当然我们这里以STL的标准来说明。
自己迭代实现删除:
vector<int>::iterator itVec = vectInt.begin();
// 删除所有值为1022的元素
for ( ; itVec != vectInt.end(); )
{
}
上面是正确的实现,容易犯的错误是在erase后还继续++inVect,这是错误的,vector内部实现erase之后itVect实际上已经指向了下一个元素,你再自增就会跳过一个元素,会引发什么问题就很难说了,如果刚好跳过了最后一个元素,还有可能程序在这个地方崩溃。list也可以用这种方法,同时list还可以用下面的方法,只有一点小改动:
list<int>::iterator itList = listInt.begin();
// 删除所有值为1022的元素
for ( ; itList != listInt.end(); )
{
}
vector不能用上面那种方法是因为vector内部是一块连续的内存,而list则是链表。
使用stl算法库中的remove remove_if来进行删除:
调用STL中算法 remove或者remove_if的陷阱,并没有真正的删除(你可以此时调用size方法来验证这一点),然后应该使用erase删除残余数据,remove或者remove_if的实现原理是用后面未被删除的元素 来覆盖前面应该被删除的元素。返回值ForwardIterator指向经移除后的最后元素的下一位置。如vector{0,1,2,3,3,4},执行remove(),希望移除所有值为3的元素,结果为{0,1,2,4,3,4},返回值ForwardIterator指向第5个元素。即:
0 1 2 3 3 4 移除前
0 1 2 4 3 4 移除后
这个方法对于自定义类型要自己实现访函数(函数对象),这里就不举例了。
两类方法的对比,其实后面的方法效率要好,如果数据大,用后面的方法,因为针对vector的话,用后面的方法不会像自己用循环去删除的时候,频繁的拷贝移动内存。
--------------------------------------------------------------------------------
3、关联式容器循环删除
for(iter = map.begin(); iter != map.end();)
{
}
因为关联式容器的erase并不返回下一个元素的迭代器,因此不能用iter = map.erase(iter)这样的表达式(有些版本的STL实现又可以这样写,我建议还是使用 map.erase(iter++)保证移植性)。
关联容器同样也可以用remove等来删除元素。
--------------------------------------------------------------------------------
4、谨慎对待操作STL容器的方法begin end size的优化,常见是将他们提取到循环的外部,如果你执行删除操作,可能导致错误,因为在进行删除操作的时候,容器的end,size很有可能随时变化。list容器的end一直不会变化,但是放在for里面,编译器也会优化。除非你能保证for循环中不会改变容器的大小。
--------------------------------------------------------------------------------
附录:
map使用:
第一种:用insert函数插入pair数据
Map<int, string> mapStudent;
mapStudent.insert(pair<int, string>(1, “student_one”));
my_Map.insert(make_pair("d",4));
第二种:用insert函数插入value_type数据
Map<int, string> mapStudent;
mapStudent.insert(map<int, string>::value_type (1, “student_one”));
第三种:用数组方式插入数据
Map<int, string> mapStudent;
mapStudent[1] =
mapStudent[2] = “student_two”
--------------------------------------------------------------------------------
转自:http://blog.sina.com.cn/s/blog_4ac0a0d30100q98z.html
- STL:循环删除容器中元素的方法和陷阱
- STL:循环删除容器中元素的方法和陷阱
- STL:循环删除容器中元素的方法和陷阱
- 循环删除容器中元素的方法和陷阱
- STL序列式容器中删除元素的方法和陷阱 一
- STL序列式容器中删除元素的方法和陷阱 二
- STL序列式容器中删除元素的方法和陷阱 三
- STL序列式容器中删除元素的方法和陷阱 四
- STL序列式容器中删除元素的方法和陷阱一
- STL序列式容器中删除元素的方法和陷阱二
- STL序列式容器中删除元素的方法和陷阱三
- STL关联式容器中删除元素的方法和陷阱四
- STL序列式容器中删除元素的方法和陷阱 一
- STL序列式容器中删除元素的方法和陷阱 二
- STL序列式容器中删除元素的方法和陷阱 三
- STL关联式容器中删除元素的方法和陷阱 四
- STL关联式容器中删除元素的方法和陷阱
- STL序列式容器中删除元素的方法和陷阱(一)
- 很有用的东西,可以修复MBR引导区,在windows命令行下mbrfix /drives 0 fixmbr就可以了
- Java进阶---对象与内存控制(三)(磨灭你的自信)
- 开发简写 对应(vc、mfc)
- iOS
- android数据存储
- 循环删除容器中元素的方法和陷阱
- Java中删除文件、删除目录及目录下所有文件
- CSS3实现超酷的图像动画变换特效
- C/C++ 获取文件长度
- Android 众多的布局属性详解
- 自动生成Makefile
- WebRTC与Ace在线代码编辑器合作,实现实时协作编程
- 数据库索引常识
- Redhat 5 中裸设备(raw) 的配置