我只是在研究函数std::remove_if
为什么不能按我预期的方式工作,并了解了C++的“擦除-删除习惯用法”,即我应该将remove
或remove_if
的结果传递给erase
,以实际从容器中删除我想要的项。
这让我觉得很不直观:这意味着remove
和remove_if
不执行它们在tin上说的话。这也会导致代码更冗长,更不清晰。
这有什么正当理由吗?我认为这是一种权衡,我在前一段中列出的好处与坏处是平衡的。
我的第一个想法是,有一些单独使用remove
或remove_if
的用例,但由于它们将集合中的剩余项保留在未定义状态,因此我想不出任何可能的用例。
2条答案
按热度按时间wpx232ag1#
这是容器/迭代器/算法范例工作方式的一个必要功能。模型的基本概念如下:
因此,算法作用于迭代器,迭代器表示某个值序列中的位置,通常由容器提供。
问题是从容器中移除一个项目并不符合这个范例,从容器中移除一个元素并不是对一个“值序列”的操作;它从根本上“改变”了序列本身的性质。
也就是说,“移除”最终以一个 * 容器操作 * 而不是迭代器操作结束。如果算法只作用于迭代器,那么没有一个纯粹的算法能够真正地“移除”元素。迭代器不知道如何做到这一点。只作用于迭代器的算法可以在序列中移动值,但它们不能改变序列的性质,从而使“移除”的值不再存在。
但是,虽然删除元素是一个容器操作...它不是一个值 * 不可知 * 操作。
remove
只删除比较等于给定值的值。remove_if
只删除 predicate 返回true的值。这些不是容器操作;它们是“算法”,并不真正关心容器的性质。除了实际从容器中移除它们的时候,从上面范例的Angular 来看,它本质上是两个独立的操作:一个算法,后面跟着一个容器操作。
尽管如此,C20还是给予a number of containers non-member
std::erase
andstd::erase_if
specializations,它们作为一个非成员函数完成了擦除的全部工作。我的第一个想法是,有一些单独使用
remove
或remove_if
的用例,但由于它们将集合中的剩余项保留在未定义状态,因此我想不出任何可能的用例。它有很多用途,多次移除是显而易见的,你可以执行一系列移除操作,只要你把新的结束迭代器传递给每一个后续的移除操作(这样就没有操作检查被移除的元素),你可以在最后做一个合适的容器
erase
。需要注意的是,C20
std::erase
和std::erase_if
函数只接受容器,而不接受容器的 * sub-section *,也就是说,它们不允许你擦除容器中的某个区域,只有erase/remove习惯用法允许这样做。此外,并非所有容器都可以擦除元素。
std::array
具有固定大小;真正的擦除元素是不允许的,但是你仍然可以使用std::remove
,只要你跟踪新的结束迭代器。cclgggtu2#
标准库中的很多算法都是在通用迭代器上操作的,不能用来删除元素,
erase
是容器的一个方法,可以访问更多的信息,所以可以用来直接删除元素。