我只是在研究为什么该函数std::remove_if
没有按我预期的方式工作,并了解了 C++“擦除删除习惯用法”,我应该将结果传递给remove
orremove_if
来erase
实际从容器中删除我想要的项目。
这让我觉得非常不直观:这意味着remove
不要remove_if
按照他们所说的去做。它还会导致代码更加冗长、不太清晰。
这有道理吗?我认为存在某种权衡,其优点可以平衡我在上一段中列出的缺点。
我的第一个想法是,有一些使用remove
或remove_if
单独使用的用例,但由于它们将集合中的其余项目留在未定义的状态,我想不出任何可能的用例。
Nic*_*las 13
这是容器/迭代器/算法范式工作方式的必要功能。该模型的基本概念如下:
因此,算法作用于迭代器,迭代器表示通常由容器提供的某些值序列中的位置。
问题是从容器中取出物品不符合这种范式。从容器中删除元素并不是对“值序列”的操作;而是对“值序列”的操作。它从根本上改变了序列本身的性质。
也就是说,“删除”最终以容器操作完成,而不是迭代器操作。如果算法仅作用于迭代器,则没有纯算法可以真正删除元素。迭代器不知道如何做到这一点。仅作用于迭代器的算法可以在序列内移动值,但它们不能改变序列的性质,使得“删除的”值不再存在。
但是,虽然元素的删除是一个容器操作......但它不是一个与值无关的操作。remove
仅删除与给定值相等的值。remove_if
仅删除谓词返回 true 的值。这些不是集装箱操作;它们是并不真正关心容器性质的算法。
除非需要将它们从容器中实际取出。从上述范式的角度来看,它本质上是两个独立的操作:算法后面是容器操作。
总而言之,C++20 确实提供了许多容器非成员std::erase
和std::erase_if
特化。它们作为非成员函数完成了擦除-删除的全部工作。
我的第一个想法是,有一些使用
remove
或remove_if
单独使用的用例,但由于它们将集合中的其余项目留在未定义的状态,我想不出任何可能的用例。
它有一些用途。多重去除是显而易见的。您可以执行一系列删除操作,只要将新的结束迭代器传递给每个后续删除(以便没有操作检查已删除的元素)。erase
最后你可以做一个合适的容器。
还应该注意的是,C++20std::erase
和std::erase_if
函数仅采用容器,而不采用容器的子部分。也就是说,它们不允许您从容器内的某个范围内进行擦除。只有擦除/删除习惯用法才允许这样做。
此外,并非所有容器都可以删除元素。std::array
有固定的尺寸;真正删除元素是不允许的。std::remove
但只要您跟踪新的结束迭代器,您仍然可以使用它们。