STL容器 erase的使用陷阱 (二)
来源:互联网 发布:多变量优化 编辑:程序博客网 时间:2024/05/22 04:41
接上一篇。
所以要彻底删除还应该把后面的残余数据删除掉,这可以通过调用容器的成员函数ERASE()做到。
从结果可以看出来,所有值为3的元素确实被删除了。
二、使用STL中通用算法或容器成员函数删除元素的方法
上一篇手工编写的FOR循环代码删除容器中元素的方法也有一些问题,如果判断条件特别复杂,又有循环判断的话,循环中间又有异常处理的话,++itVect的位置就要小心放置了,稍不留意就要出错,所以手工编写代码删除容器中元素的方法不太安全,代码重复,也不够优雅,要注意的地方很多。
对于这种情况,可以考虑使用STL中通用算法remove()和Remove_if()帮忙。而Remove()和Remove_if()这两个算法也有一个问题需要程序员特别小心,在通用算法中的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 移除后
移除值为3的元素,移除后3被其后的4替代,最后两位元素为残余数据。
例5:
- void main() {
- vector<int> vectInt;
- int i;
- for (i = 0; i < 5; i++ ) {
- vectInt.push_back( i );
- if ( 3 == i ) {
- vectInt.push_back( i );
- }
- }
- remove( vectInt.begin(), vectInt.end(), 3 );
- cout << " after deleted , size = " << vectInt.size() << endl;
- for ( i = 0; i < vectInt.size();; i++ ) {
- cout << "i = " << i << " , " << vectInt[i] << endl;
- }
- }
- 运行结果为:
- after deleted , size = 6 // 从这行可以看出,移除后容器的大小没变
- i = 0 , 0
- i = 1 , 1
- i = 2 , 2
- i = 3 , 4 //从这行可以看出:“应被删除的元素”3 被其后的“未被删除的元素”4覆盖
- i = 4 , 3
- i = 5 , 4
例6:
- void main() {
- vector<int> vectInt;
- int i;
- for (i = 0; i < 5; i++ ) {
- vectInt.push_back( i );
- if ( 3 == i ) {
- vectInt.push_back( i );
- }
- }
- vectInt.erase( remove( vectInt.begin(), vectInt.end(), 3 ), vectInt.end() );
- cout << " after deleted , size = " << vectInt.size() << endl;
- for ( i = 0; i < vectInt.size();; i++ ) {
- cout << "i = " << i << " , " << vectInt[i] << endl;
- }
- }
- 运行结果为:
- after deleted , size = 4 // 从这行可以看出,删除后容器的大小变化了
- i = 0 , 0
- i = 1 , 1
- i = 2 , 2
- i = 3 , 4
对于Vector容器存放其他比较复杂的对象,就可以用remove_if()加函数对象的方法。
例7:
- #include <iostream>
- #include <sstream>
- #include <string>
- #include <vector>
- #include <algorithm>
- #include <list>
- using namespace std;
- class CTest
- {
- public:
- CTest(const string& str, int iPrice):m_strName(str),m_iPrice(iPrice){}
- void vPrint(){ cout<<"name=" << m_strName << "price=" << m_iPrice <<endl;}
- private:
- string m_strName;
- int m_iPrice;
- // 由于两个函数对象要访问CTest类的Private成员,所以设为友员;
- friend class CStrFunc;
- friend class CIntFunc;
- };
- // 函数对象,根据string比较
- class CStrFunc
- {
- string m_str;
- public:
- CStrFunc(const string& str):m_str(str){ }
- bool operator() (const CTest& left) { return (m_str == left.m_strName)?true:false; }
- };
- // 函数对象,根据int比较
- class CIntFunc
- {
- int m_iPrice;
- public:
- CIntFunc(int iPrice):m_iPrice(iPrice){ }
- bool operator()(const CTest& left) { return (m_iPrice == left.m_iPrice)?true:false; }
- };
- void main()
- {
- vector<CTest> vectTest;
- int i;
- for(i=0;i<5;++i)
- {
- stringstream stream; // 流格式化符,把int转化为string;
- stream<<i;
- string str = stream.str();
- CTest dTest(str,i);
- vectTest.push_back(dTest);
- }
- for ( i = 0 ; i < vectTest.size(); i++ )
- {
- vectTest[ i ].vPrint();
- }
- // 删除所有m_strName = "3"的元素
- vectTest.erase( remove_if( vectTest.begin(), vectTest.end(), CStrFunc( "3" ) ), vectTest.end() );
- cout << "delete 3 after : " << endl;
- for ( i = 0 ; i < vectTest.size(); i++ )
- {
- vectTest[ i ].vPrint();
- }
- // 删除所有m_iPrice = 2的元素
- vectTest.erase( remove_if( vectTest.begin(), vectTest.end(), CIntFunc( 2 ) ),vectTest.end() );
- cout << "delete 2 after : " << endl;
- for ( i = 0 ; i < vectTest.size(); i++ )
- {
- vectTest[ i ].vPrint();
- }
- }
手工编写for循环代码删除STL序列式容器中元素的方法,使用STL中通用算法或容器成员函数删除元素的方法,两者之间的比较:
1. 前者代码重复。
2. 前者容易出错,不够清晰。
3. 效率:
0 1 2 3 2 5 6 7
0 1 3 2 5 6 7
0 1 3 5 6 7
用第一种方法删除所有值为2的元素
从上图可以看出,每删除一个元素,后面的所有元素都到往前移动一位,导致一次内存大搬迁。
0 1 2 3 2 5 6 7
0 1 3 2 5 6 6 7
0 1 3 5 6 7
用第二种方法删除所有值为2的元素
从上面可以看出,删除时元素2被后面元素覆盖,不会到元素移位和内存大搬迁,残余数据留到末尾一次全部删除,也不会导致内存大搬迁,所以后者的方法要比前者在效率上好很多。
1. 前者代码重复。
2. 前者容易出错,不够清晰。
3. 效率:
0 1 2 3 2 5 6 7
0 1 3 2 5 6 7
0 1 3 5 6 7
用第一种方法删除所有值为2的元素
从上图可以看出,每删除一个元素,后面的所有元素都到往前移动一位,导致一次内存大搬迁。
0 1 2 3 2 5 6 7
0 1 3 2 5 6 6 7
0 1 3 5 6 7
用第二种方法删除所有值为2的元素
从上面可以看出,删除时元素2被后面元素覆盖,不会到元素移位和内存大搬迁,残余数据留到末尾一次全部删除,也不会导致内存大搬迁,所以后者的方法要比前者在效率上好很多。
- STL容器 erase的使用陷阱 (二)
- STL容器erase的使用陷阱
- STL容器 erase的使用陷阱 (一)
- STL容器erase的使用陷阱(三)
- STL容器erase的使用陷阱(三)
- STL容器erase的使用陷阱(三)
- 关于STL常用容器的erase使用陷阱
- STL容器中erase方法的不同陷阱
- STL中容器操作的迭代器失效-erase()函数陷阱
- 迭代器失效(1)-小心使用STL容器的erase()
- 迭代器失效(1)-小心使用STL容器的erase()
- C++ STL容器中erase的使用
- STL容器 erase的使用陷井
- STL容器的erase用法
- STL中容器的erase()
- stl容器跨模块使用的陷阱
- 注意C++ STL容器中erase的使用
- STL的erase()陷阱-迭代器失效总结
- flex 学习笔记
- Opensparc T1概述(硬件)
- 测试相关工具
- outlook2007 邮件正文出现乱码,如何解决?
- 金蝶称与IBM业务合作不受雷曼破产影响
- STL容器 erase的使用陷阱 (二)
- linux vi的使用
- Oracle10g中的回收站
- 鬼泣4中把所有的剧情和通过动画串连为一个完整动画电影的看法
- js 显示百分数
- Nehalem是什么吗
- uC/OS-II 初级程序员指南
- DDK Source Files Allot
- 向Sigma8634移植DirectFB