删除STL容器元素的方法

23 篇文章 22 订阅

STL中,要删除容器内的一个元素,其方法会随着容器类型的不同而不同。

 

一、删除特定值的元素

例如,对于STL容器c,c包含int类型的元素,现在需要删除c中等于2014的元素。

Container<int> c;

1. 序列容器

序列容器即具有连续内存的容器,如vector,deque,string,其删除特定值的元素的方法最好是使用erase-remove用法。

// 当c是vector,deque,string,使用erase-remove方法
c.erase(remove(c.begin(), c.end(), 2014), c.end());  

对于list,则直接可以调用remove方法。

// 当list时,remove方法是删除特定值元素的最好方法
c.remove(2014);

2. 关联容器

若c是关联容器,即c是set或者map等类型,则正确方法是使用erase方法。

// 若c是关联容器,则erase方法是删除特定值元素的最好方法
c.erase(2014);

二、删除满足特定条件的元素

对于容器c,需要删除使下面判别式为true的每一个元素:

bool predicate(int);

1. 序列容器

对于序列容器,vector,deque,string,list,把每个remove的调用换成调用remove_if就行了:

// 当c是vector,deque,string时,使用erase-remove_if是删除满足特定条件元素的最好方法
c.erase(remove_if(c.begin(), c.end(), predicate), c.end());
// 当c是list时,remove_if是删除满足特定条件元素的最好方法
c.remove_if(predicate);

2. 关联容器

关联容器并没有提供类似remove_if的方法,因此须写一个循环来遍历c中的所有元素,并在遍历过程中删除满足特定条件的元素。 

下面的代码是很多程序员首先能想到的。

 

AssocContainer<int> c;
for (AssocContainer<int>::iterator it = c.begin(); it != c.end(); ++it) {
	if (predicate(*it))
		c.erase(it);
}

可是,当关联容器中的一个元素被删除时,指向该元素的所有迭代器都将失效。一旦执行了c.erase(it),it就变成无效的值。

 

为了避免这个问题,我们要确保在调用erase之前,有一个迭代器指向c中的下一个元素。下面的代码演示了这个方法。

AssocContainer<int> c;
for (AssocContainer<int>::iterator it = c.begin(); it != c.end(); ) {
	if (predicate(*it))
		c.erase(it++);
	else
		it++;
}

 

对于序列容器,如果也要通过遍历循环来删除特定的元素,则不能使用上面的删除关联容器特定元素的方法,因为对vector,string,deque这类序列容器来说,调用erase不仅会使指向被删除元素的迭代器失效,而且也会使被删除元素之后的所有迭代器失效。

下面代码演示了序列容器使用遍历循环来删除元素的方法。

 

SeqContainer<int> c;
for (SeqContainer<int>::iterator it = c.begin(); it != c.end(); /* 啥也不做 */) {
	if (predicate(*it))
		it = c.erase(it); // 把erase的返回值赋给it,使it的值保持有效
	else
		++it;
}

值得注意的是,这种 方法仅对序列容器适用。对于关联容器,若erase的参数是迭代器(erase的参数也可以是里面的元素),则返回值是void。所以上面的方法并不适用于关联容器。
 

 

 

参考资料:

《Effective STL》第三版

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值