代码之家  ›  专栏  ›  技术社区  ›  Bri Bri

为什么C++有“删除”这个成语?

c++
  •  2
  • Bri Bri  · 技术社区  · 2 年前

    我只是想知道为什么 std::remove_if 没有按我预期的方式工作,并学习了C++“擦除-删除习语”,在这里我应该传递 remove remove_if erase 以实际从容器中删除我想要的项目。

    这让我觉得很不直观:这意味着 去除 删除if 不要照罐头上说的做。它还使得代码更加冗长、不那么清晰。

    这有正当理由吗?我认为,在平衡我在上一段中列出的不利因素的同时,也存在某种权衡。

    我的第一个想法是,使用 去除 删除if 它们自己,但由于它们将集合中的其余项保留为未定义状态,我想不出任何可能的用例。

    2 回复  |  直到 2 年前
        1
  •  11
  •   Nicol Bolas    2 年前

    这是容器/迭代器/算法范例工作方式的一个必要功能。该模型的基本概念如下:

    • 容器包含并管理值序列。
    • 算法作用于值序列。
    • 迭代表示一系列值中的可移动位置。

    因此,算法作用于迭代器,迭代器表示某个值序列中的位置,通常由容器提供。

    问题是从容器中移除一个项目不符合这种模式。从容器中移除元素不是对“值序列”的操作;它从根本上 更改 序列本身的性质。

    也就是说,“删除”最终以 集装箱作业 ,而不是迭代器操作。如果算法只作用于迭代器,那么没有一个纯算法能够真正 去除 元素。迭代程序不知道该怎么做。只作用于迭代器的算法可以在序列中移动值,但它们不能改变序列的性质,从而使“删除”的值不再存在。

    但是,虽然元素的移除是一个容器操作。。。这不是价值 不可知论者 活动 remove 仅删除与给定值比较相等的值。 remove_if 仅删除谓词返回true的值。这些不是集装箱作业;他们是 算法 他们并不真正关心容器的性质。

    除非到了真正将它们从容器中移除的时候。从上述范式的角度来看,它本质上是两个独立的操作:一个是算法,然后是容器操作。

    尽管如此,C++20确实给出了 a number of containers non-member std::erase and std::erase_if specializations 。它们作为非成员函数完成擦除删除的全部工作。

    我的第一个想法是,使用 去除 删除if 它们自己,但由于它们将集合中的其余项保留为未定义状态,我想不出任何可能的用例。

    它有很多用途。多次移除是显而易见的。您可以执行一系列移除操作,只要将新的结束迭代器传递给后续的每次移除(这样就不会有任何操作检查已移除的元素)。你可以做一个合适的容器 erase 最后。

    还应该注意的是,C++20 std::擦除 标准::擦除_if 函数只接受容器,不接受 小节 集装箱。也就是说,它们不允许您从容器内的某个范围进行擦除。只有擦除/移除习惯用法允许这样做。

    此外,并非所有容器 可以 擦除元件。 std::array 具有固定的大小;真正擦除元素是不允许的。但你仍然可以 std::remove 使用它们,只要您跟踪新的结束迭代器。

        2
  •  6
  •   Unmitigated    2 年前

    标准库中的许多算法都在通用迭代器上运行,而这些迭代器不能用于删除元素。 erase 是容器的一种方法,可以访问更多信息,因此可以使用它直接删除元素。