我正在写一个或多或少像这样的程序:
#include <list>
list<MyClass> things;
class MyClass {
// some stuff
void remove() {
things.remove_if(THING_IS_ME);
}
};
Run Code Online (Sandbox Code Playgroud)
我需要写什么而不是THING_IS_ME?
换句话说,我使用全局STL列表作为事物的集合.在某些时候,列表中的对象识别出它是多余的并且想要a)将自己从列表中移除,并且b)使自己被破坏.
我该怎么做呢?
我已经写了大约15年的C++并且在这个页面上有点困惑:http://www.cplusplus.com/reference/algorithm/remove_if/
这些谓词是什么?C++现在有更高阶的功能吗?
在过去的15年中,C++的情况发生了巨大变化.1994年7月,亚历山大·斯捷潘诺夫(Alexander Stepanov)提出的关于通用编程理念的图书馆的提议获得了ANSI/ISO委员会的最终批准.我们今天方便地称之为STL的库随后成为标准C++库.STL的故事与它背后的想法一样迷人,它绝对值得一读.
std::remove_if()你发现的功能只是这种哲学的另一种反映,它成为了C++现代身份的一部分.简而言之,这是一个通用函数,可以处理任何元素的容器(序列)和任何(表现为a)的条件.为此,您必须提供两个功能:
事实证明,在这种情况下,您想要的谓词是相等的谓词.并且因为基于相等性去除元素是如此常见的任务,所以标准还提供了std::remove()假定隐式等式谓词的函数.当然,您必须确保元素可以比较:
bool operator==(const MyClass& a, const MyClass& b)
{
// return true if the two are equal, and false otherwise.
}
Run Code Online (Sandbox Code Playgroud)
然后我们可以使用我们的谓词来删除类型的元素MyClass:
std::remove(things.begin(), things.end(), *this); // if *this == elem
Run Code Online (Sandbox Code Playgroud)
回想一下,标准函数std::remove()适用于任何容器,甚至是尚未创建的容器.因为每种容器都有自己的删除元素的方法,所以如果不知道它所使用的容器的实现细节,这个函数就无法真正执行删除.因此,该std::remove()函数交换元素,使得"移除"元素位于容器的末尾.然后,它返回一个迭代器,指向连续元素"removed"的第一个元素.
typedef std::list<MyClass>::iterator iter;
iter first_removed = std::remove(things.begin(), things.end(), *this);
Run Code Online (Sandbox Code Playgroud)
最后,我们通过调用特定容器的删除功能来真正删除元素,该功能适用于列表中的单个位置或要删除的一系列连续元素:
things.erase(first_removed, things.end());
Run Code Online (Sandbox Code Playgroud)
在一行中看到这种代码并不罕见:
things.erase(std::remove(things.begin(), things.end(), *this),
things.end());
Run Code Online (Sandbox Code Playgroud)
这一切看起来都是压倒性的和复杂的,但它有一些优点.首先,标准库的这种设计支持动态编程.它还允许标准库提供具有非常纤薄的接口的容器,以及几种可用于许多不同类型容器的自由功能.它允许您快速创建容器并立即获得标准库的所有功能以使用它.或者,它允许您快速编写一个通用函数,该函数可立即与所有标准容器一起使用 - 已经写好的那些容器和那些尚未写入的容器.
| 归档时间: |
|
| 查看次数: |
5387 次 |
| 最近记录: |