C++ 在C++;,从列表中删除对象

C++ 在C++;,从列表中删除对象,c++,stl,remove-if,C++,Stl,Remove If,我在写一个程序,大致是这样的: #include <list> list<MyClass> things; class MyClass { // some stuff void remove() { things.remove_if(THING_IS_ME); } }; #包括 列出事情; 类MyClass{ //一些东西 作废删除(){ 事物。如果(事物是我的话)移除; } }; 我需要写什么来代替我 换句话说,我使用一个全局S

我在写一个程序,大致是这样的:

#include <list>

list<MyClass> things;

class MyClass {
   // some stuff

   void remove() {
       things.remove_if(THING_IS_ME);
   }
};
#包括
列出事情;
类MyClass{
//一些东西
作废删除(){
事物。如果(事物是我的话)移除;
}
};
我需要写什么来代替我

换句话说,我使用一个全局STL列表作为一个集合。在某种程度上,列表中的对象会识别出它是冗余的,并希望a)将自身从列表中删除,b)将自身销毁

我该怎么做

<>我已经写了15年的C++了,我对这里的页面有点困惑:


这些谓词是什么?C++现在是否具有高阶函数?

第一,简单手写循环:

for( list<MyClass>::iterator it = things.begin(); it != things.end(); /*  */ ) {
    if( qualifiesForDelete( *it ) ) {
        it = things.erase( it );
    }
    else {
        ++it;
    }
}

其中,
deletionPredicate
是一个函数或函数对象,它接受一个类型为的参数并返回
bool
。返回
true
的元素被视为已删除

首先,一个简单的手写循环:

for( list<MyClass>::iterator it = things.begin(); it != things.end(); /*  */ ) {
    if( qualifiesForDelete( *it ) ) {
        it = things.erase( it );
    }
    else {
        ++it;
    }
}
其中,
deletionPredicate
是一个函数或函数对象,它接受一个类型为的参数并返回
bool
。返回
true
的元素被视为已删除

(最初是一组注释,但在发现OP真正想要做的事情后重写为答案。)


您知道STL容器存储您插入的内容的副本,对吗?这意味着
MyClass
的实例最好具有可比性(例如,通过
operator==
)-您不能只比较地址,因为它们总是不同的

如果拥有MyClass的副本没有任何意义,那么你最好还是使用它

,C++语言默认使用复制语义。该语言要求您在代码中明确引用之类的内容。我强烈建议您重新开始,否则您将在将来被类似的问题绊倒。

(最初是一组注释,但在发现OP真正想要做的事情后重写为答案。)


您知道STL容器存储您插入的内容的副本,对吗?这意味着
MyClass
的实例最好具有可比性(例如,通过
operator==
)-您不能只比较地址,因为它们总是不同的

如果拥有MyClass的副本没有任何意义,那么你最好还是使用它


,C++语言默认使用复制语义。该语言要求您在代码中明确引用之类的内容。我强烈建议您重新开始,否则将来会被类似的问题绊倒。

如果
函数包含三个参数,则
remove\u:两个迭代器定义您正在处理的范围,以及一个谓词(返回
bool
的测试函数)。开始迭代器指向要处理的第一个元素;结束迭代器指向范围中最后一个元素之后的元素

在来自的示例中,谓词是表示

bool IsOdd (int i) { return ((i%2)==1); }
要使代码实现您想要的功能,您需要编写如下内容:

things.remove_if(things.begin(), things.end(), SomePredicateFunction);
您可以这样定义
SomePredicateFunction
(用适当的测试替换
true
):


remove\u if
函数有三个参数:两个迭代器定义正在处理的范围,以及一个谓词(返回
bool
的测试函数)。开始迭代器指向要处理的第一个元素;结束迭代器指向范围中最后一个元素之后的元素

在来自的示例中,谓词是表示

bool IsOdd (int i) { return ((i%2)==1); }
要使代码实现您想要的功能,您需要编写如下内容:

things.remove_if(things.begin(), things.end(), SomePredicateFunction);
您可以这样定义
SomePredicateFunction
(用适当的测试替换
true
):


在过去的15年里,C++的情况发生了巨大的变化。1994年7月,亚历山大·斯捷潘诺夫(Alexander Stepanov)提出的一个包含他关于泛型编程思想的库的建议得到了ANSI/ISO委员会的最终批准。我们今天方便地调用的这个库后来成为标准的C++库。STL的故事和它背后的思想一样引人入胜,绝对值得一读

您发现的
std::remove_if()
函数只是这种哲学的另一个反映,它已成为C++现代身份的一部分。简言之,这是一个通用函数,它将在元素的任何容器(序列)和任何(行为类似于)条件下工作。为此,您必须提供两个功能:

  • 两个迭代器,用于限定要处理的元素范围
  • 以及一个谓词,当对元素调用时,如果要删除该元素,则返回true,否则返回false
  • 事实证明,在本例中,您需要的谓词是相等谓词。由于基于相等性删除元素是一项非常常见的任务,因此该标准还提供了
    std::remove()
    函数,该函数采用隐式相等谓词。当然,您必须确保元素可以比较:

    bool operator==(const MyClass& a, const MyClass& b)
    {
        // return true if the two are equal, and false otherwise.
    }
    
    然后,我们可以使用谓词删除
    MyClass
    类型的元素:

    std::remove(things.begin(), things.end(), *this);  // if *this == elem
    
    回想一下,标准函数
    std::remove()
    适用于任何容器,即使是尚未创建的容器。因为每种容器都有自己的删除元素的方法,所以如果不知道它所使用的容器的实现细节,这个函数就不能真正执行删除。因此,
    std::remove()
    函数交换周围的元素,使元素“removed”位于容器的末尾。然后,它返回一个迭代器,该迭代器指向“删除”的连续元素中的第一个元素

    在一行中看到此类代码并不少见:

    things.erase(std::remove(things.begin(), things.end(), *this),
                 things.end());
    
    这一切都可能是错误的
    things.erase(std::remove(things.begin(), things.end(), *this),
                 things.end());