STL容器的删除元素问题
来源:互联网 发布:网络低俗词 编辑:程序博客网 时间:2024/05/22 11:57
STL的容器分为两类,一类是序列式容器,即数据顺序连续存储,如:vector、deque;另一类是关联式容器,即数据不连续存储,如:map、list、set。对于STL容器的数据删除操作,有一些需要注意的地方。
1、序列式容器的数据删除
下面例子以容器list为例:
for (list<int>::iterator iter = lst.begin(); iter != lst.end(); iter++){ if (符合条件) { lst.erase(iter); }}
上面的代码,乍一看好像是没有什么问题,一个再普通不过的for循环而已,怎么会有问题呢?问题就是出在erase函数上了,对于关联式容器,erase函数会删除传入的迭代器指向的元素,并回收迭代器指向的内存空间,此时该迭代器已经失效。这下问题就清晰了,上面的代码若进行了erase操作后,迭代器iter已经失效了,而for循环的iter++接着会对一个已失效的迭代器iter进行++操作,这种操作不可预期,可能会造成程序crash。
正确的使用方法有以下两种:
方法一:
当erase函数执行完之后,会返回下一个有效节点,因此可以使用以下方法
for (list<int>::iterator iter = lst.begin(); iter != lst.end();){ if (符合条件) { iter = lst.erase(iter); } else { iter++; }}
方法二:
下面写法中,iter的后置++操作会完成两件事,第一是返回iter的一个副本,这个副本和iter本身都指向同一内存地址;第二是对iter自身进行了++操作,此时iter还是有效的,而且指向下一个有效节点。而副本则作为实参传给了erase函数,在erase函数中,副本所指的内存空间会被回收,副本会失效。可以简单理解为,在iter被删除之前就已经执行了++操作。
for (list<int>::iterator iter = lst.begin; iter != lst.end();){ if (符合条件) { lst.erase(iter++); } else { iter++; }}
2、序列式容器的数据删除
对于序列式容器vector、deque的数据删除操作,也有一些点需要注意的,以vector为例,下面代码目标是删除vector中满足条件的数据:
vector<int> vec;//插入数据for (int i = 0; i < 5; ++i){ vec.push_back(i);}//过滤并打印数据for (vector<int>::iterator iter = vec.begin(); iter != vec.end(); ++iter){ //删除值为0的数据 if (0 == *iter) { vec.erase(iter); } else { cout<<*iter<<"\t"; }}我们期望的输出结果应该是:1 2 3 4
可是,上面代码实际输出结果却是:2 3 4,为什么会出现这种情况呢?这就涉及到容器vector本身数据结构的特点和erase()函数的作用问题了。由于vector是序列式容器,数据在其中是连续存储的,当调用了erase()函数删除其中的某个元素时,会将删除元素的下一个有效元素覆盖删除元素的所在位置的数据。
这下子,对于上面代码的输出结果就清晰了,当0元素被删除后,iter已经指向了1元素,而for循环的++iter操作则将iter再递增一次,使得iter指向了2元素,导致跳过了1元素,因此就出现了上面的输出结果了。假如有两个0元素连续存放,还会跳过第二个0元素的,导致没有完全过滤掉满足条件的数据,这个问题算是比较难发现的。
上面的代码可能会导致满足条件的数据没有被删除,但是在某些情况下,可能还会出现coredump问题,还是针对上面的例子,将上面代码的“过滤并打印数据”部分替换为以下代码,即删除值为4的数据:
//过滤并打印数据for (vector<int>::iterator iter = vec.begin(); iter != vec.end(); ++iter){ //删除值为4的数据 if (4 == *iter) { vec.erase(iter); } else { cout<<*iter<<"\t"; }}
二话不说,程序直接segmentation fault。当执行完erase之后,iter已经指向vec.end(),而for循环的++iter,再将iter递增一次,此时iter越界了,当执行*iter时,就导致了非法访问内存,程序crash。
- STL容器的删除元素问题
- STL容器的删除元素问题
- STL容器元素的删除
- STL 删除容器中元素的几个特殊问题
- 关于STL容器中vector特定元素的删除问题
- STL容器删除元素的陷阱(转)
- STL容器删除元素的陷阱
- 删除STL容器元素的方法
- stl容器遍历删除元素
- STL容器之 元素删除
- 安全删除STL容器元素
- STL容器中元素的删除的惯用法
- STL:循环删除容器中元素的方法和陷阱
- STL:循环删除容器中元素的方法和陷阱
- STL:循环删除容器中元素的方法和陷阱
- stl容器在循环遍历中删除元素的方式
- STL容器:在遍历的过程中删除元素
- STL序列式指针容器中删除元素的方法
- Android网络编程实践之旅(二):基于Socket的网络通信
- Redis数据结构型数据库及其常用操作
- Hadoop --基础知识-合并文件简单示例
- Qt断点续传(暂停下载任务)
- 微软对Windows XP 的支持将在2014年4月8日结束
- STL容器的删除元素问题
- ThreadLocal使用
- 开题报告写作重点及注意要点
- GLSL入门2 关于GLSL中的纹理贴图
- WMI--Windows API--CoSetProxyBlanket
- TYVJ 1023 奶牛的锻炼
- Android网络编程实践之旅(二):基于Socket的网络通信
- 谨慎优化代码
- 深入了解字符集和编码问题