您的位置:首页 > 其它

删除STL容器元素的方法

2014-04-05 17:17 162 查看
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》第三版
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: