容器删除元素的方法(备份csdn博客,防止删除)
Effective STL 第一章 第9条
1、要删除容器中有特定值的所有对象;2、要删除容器中满足特定判断式(条件)的所有对象;
3、要在循环内部做某些(除了删除对象之外的)操作。
完全复制粘贴自https://blog.csdn.net/xlf13872135090/article/details/18040955,该博客总结至《Effective STL 第一章 第9条》,本文主要作用为备份,防止突然找不到。
先写总结,在写例子:
1、要删除容器中有特定值的所有对象:
如果容器是vector, string或deque,则使用erase-remove习惯用法
如果容器是list,则使用list::remove
如果容器是一个标准关联容器,则使用它的erase成员函数
2、要删除容器中满足特定判断式(条件)的所有对象:
如果容器是vector、string和deque,则使用erase-remove-if用法
如果容器是list, 则使用list::remove_if
如果容器是一个标准关联容器,则使用remove_copy_if和swap,或者写一个循环来遍历容器中的元素,当把迭代器传给erase时,要对它进行后缀递增。
3、要在循环内部做某些(除了删除对象之外的)操作:
如果容器是一个标准序列容器,则写一个循环来遍历容器中的元素,每次调用erase时,要用它的返回值更新迭代器
如果容器是一个标准关联容器,则写一个循环来遍历容器中的元素,每次迭代器传给erase时,要对它进行后缀递增
以下是例子:
假定一个容器c,包含int类型,Container
问题1:当要删除c中所有值为1963的元素
(1)如果是一个连续内存容器(vectordeque string),使用erase-remove方法
remove操作并没有移除元素,而是将后面的元素覆盖删除元素,
返回新区间的逻辑终点,即下一个没有被删除的位置
(注意这里会使原来及其后面的迭代器失效,因为指向了不正确的元素)
erase删除两个迭代器之间的元素
1 |
|
(2)对于list,这一办法同样适用,但是适用list成员函数remove更高效
1 |
|
(3)当c是标准关联容器(set multiset map multimap)时,不能使用remove操作,
因为没有这个成员函数,使用remove算法可能会覆盖容器的值,同时可能会破坏容器
正确方法是 调用erase
1 |
|
问题2:如果是使下面判断式返回true的每一个对象
1 |
|
(1) 对于序列容器(vectorstring deque list),对remove的调用换成remove_if就可以
1 |
|
(2)对于标准关联容器,解决方案有两种:
第一种:利用remove_copy_if把我们需要复制的值复制到一个新容器中,然后把原来容器的内容和新容器的内容相互交换:
1 |
|
缺点是:需要复制所有不被删除的元素
不能直接从原始的容器中删除元素,因为容器没有提供类似remove_if的成员函数。
第二种:可以写一个循环,在遍历过程中删除元素。
一个直截了当的方法:
1 |
|
但是这样会导致不确定的行为,当容器中的一个元素被删除时,指向该元素的所有迭代器都变得无效,c.erase(i)之后,i变为无效值。
为了避免这个问题,要确保在调用erase之前,有一个迭代器指向c中的下一个元素。
最简单的方法是,对i使用后缀++
1 |
|
问题3:如果我们不仅要删除使badValue返回true的元素,还当元素被删除时向日志文件记录一条信息
1 |
|
这种方法对vector string deque无效,会导致不确定行为,因为这种容器调用erase不仅会使指向被删除元素的迭代器无效,也会使被删除元素之后的所有迭代器失效(因为容器位置变了,原来指向的内容已经变了),++i,–i都会无效。
所以对于vector string deque,利用erase的返回值。返回值是我们所需要的,一旦erase完成,它是指向紧随被删除元素的下一个元素的有效迭代器。
1 |
|
对于list来说,一般是对list采用和vector string deque相同的方式。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!