分享
 
 
 

STL序列式容器中删除元素的方法和陷阱 二

王朝other·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

2.使用STL中通用算法或容器成员函数删除元素的方法

以上手工编写for循环代码删除容器中元素的方法也有一些问题,如果判断条件特别复杂,又有循环判断的话,循环中间又有异常处理的话,++itVect的位置就要小心放置了,稍不留意就要出错。所以手工编写代码删除容器中元素的方法不太安全,代码重复,也不够优雅,要注意的地方很多。

对于这种情况,可以考虑使用STL中通用算法remvoe()和remove_if()帮忙。而remvoe()和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

所以要彻底删除还应该把后面的残余数据删除掉,这可以通过调用容器的成员函数erase()做到。

例 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

从结果可以看出,所有值为3的元素确实被删除了。

对于vector容器存放其他比较复杂的对象,就可以用remove_if()加函数对象(Function Object)的方法。

如:

例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 clTest( str, i );

vectTest.push_back( clTest );

}

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被后面元素覆盖,不会到元素移位和内存大搬迁,残余数据留到末尾一次全部删除,也不会导致内存大搬迁,所以后者的方法要比前者在效率上好很多。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有