在过去的 15 年里,C++ 发生了巨大的变化。1994 年 7 月,Alexander Stepanov 提出的包含他的泛型编程思想的库的提议获得了 ANSI/ISO 委员会的最终批准。这个我们今天方便地称为 STL 的库随后成为标准 C++ 库。STL 的故事与其背后的想法一样引人入胜,绝对值得一读。
您发现的std::remove_if()
函数只是这种哲学的另一种反映,它已成为 C++ 现代身份的一部分。简而言之,这是一个通用函数,适用于任何元素容器(序列)和任何(行为类似于 a)条件。为此,您必须为函数提供两件事:
- 几个迭代器,它们划定了您希望处理的元素范围;
- 和一个谓词,当在元素上调用时,如果要删除该元素,则返回 true,否则返回 false。
事实证明,在这种情况下,您想要的谓词是相等的谓词。并且由于基于相等性删除元素是一项常见任务,该标准还提供了std::remove()
假设隐式相等谓词的功能。当然,您必须确保元素可以比较:
bool operator==(const MyClass& a, const MyClass& b)
{
// return true if the two are equal, and false otherwise.
}
然后我们可以使用我们的谓词来删除 type 的元素MyClass
:
std::remove(things.begin(), things.end(), *this); // if *this == elem
回想一下,标准函数std::remove()
适用于任何容器,即使是尚未创建的容器。因为每种容器都有自己的移除元素的方式,所以如果不知道它所处理的容器的实现细节,这个函数就无法真正执行移除。因此,该std::remove()
函数会交换元素,以使“删除”的元素位于容器的末尾。然后,它返回一个迭代器,指向“已删除”的连续元素的第一个元素。
typedef std::list<MyClass>::iterator iter;
iter first_removed = std::remove(things.begin(), things.end(), *this);
最后,我们通过调用特定容器的删除函数来真正删除元素,该函数适用于列表中的单个位置或一系列要删除的连续元素:
things.erase(first_removed, things.end());
在一行中看到这种代码并不少见:
things.erase(std::remove(things.begin(), things.end(), *this),
things.end());
这一切可能看起来势不可挡和复杂,但它有一些优点。一方面,标准库的这种设计支持动态编程。它还允许标准库提供具有非常苗条接口的容器,以及适用于许多不同类型容器的少量免费函数。它允许您快速创建一个容器并立即获得标准库的所有功能来使用它。或者,它允许您快速编写一个通用函数,该函数可以立即与所有标准容器一起工作——那些已经编写的和尚未编写的。