C++ - std::list remove_if 不会释放内存?

C++ - std::list remove_if doesn't deallocate memory?

本文关键字:释放 if 内存 std list remove C++      更新时间:2023-10-16

可能重复:
std::list::remove方法是否调用每个被移除元素的析构函数?

我有一个Parent类,并将两个孩子Foo和Bar子类化。类声明看起来像这样:

class Parent {
    public:
        virtual void action()=0;
        std::string getName() {return name;}
        Parent(std::string name): name(name) {}
        virtual ~Parent() {}
    private:
        std::string name;
}
class Foo {
    public:
        virtual void action(); //Declared somewhere else.
        Foo(int a, int b, unsigned long c, std::string name): Parent(name),a(a),b(b),c(c) {}
        virtual ~Foo() {}
    private:
        int a,b;
        unsigned long c;
}

Bar看起来和Foo差不多。我不认为他们的行动职能和私人成员的差异会有多大区别(这也是一堆int)。

我需要列出一份家长名单,里面有Foos和Bars。我这样做是为了添加它们,然后删除它们:

std::list<Parent *> pList;
pList.push_back(new Foo(1,2,3,"Thing"));
removeFromList(&pList, "Thing");

其中removeFromList定义如下:

// Binary predicate struct, find objects with matching name.
struct NameMatch : public std::binary_function< Parent*, std::string, bool > {
     bool operator () (Parent* p, const std::string name) const {
         return (p->getName()==name);
     }
};
/* Removes a named object from the list of Foos. 
   Does nothing if a matching name can't be found. */
void removeFromList(std::list<Parent *> *pList, std::string name) {
    pList->remove_if(std::bind2nd(NameMatch(),name));
}

然而,一旦我退出程序,Valgrind就会报告内存泄漏,其中main.cpp引用的行是列表上完成的push_back操作:

==14230== 949 (520 direct, 429 indirect) bytes in 13 blocks are definitely lost in loss record 52 of 61
==14230==    at 0x4C28B35: operator new(unsigned long) (vg_replace_malloc.c:261)
==14230==    by 0x4026C8: main (main.cpp:93)
==14230== 
==14230== 5,970 (960 direct, 5,010 indirect) bytes in 30 blocks are definitely lost in loss record 60 of 61
==14230==    at 0x4C28B35: operator new(unsigned long) (vg_replace_malloc.c:261)
==14230==    by 0x40296A: main (main.cpp:112)

这是否意味着列表的remove_if函数不会释放内存,或者我在其他地方犯了错误?我该如何确保我的程序不会因为使用这些类而泄露内存?第二双眼睛会很有帮助。

提前感谢!(哦,仅供参考,我不能使用Boost库进行此任务)

您的列表包含指向对象的指针。您只是移除了指针,而不是释放它所指向的内存(破坏对象)。在移除指针之前,您需要对其调用delete。这意味着list::remove_if无法在此处执行此操作。您需要遍历列表,删除每个符合条件的对象,并使用迭代器调用list::erase

这里没有简单的出路。您需要运行时多态性,因此需要指针,并且不能使用boost::shared_ptr。也许你可以作弊并使用std::shared_ptrstd::unique_ptr;)