【问题标题】:Use Destructor to Delete Heap-allocated Objects in Member Vector使用析构函数删除成员向量中的堆分配对象
【发布时间】:2017-10-03 02:16:54
【问题描述】:

我想解决一个递归问题。如果给定动作是可能的,则可能存在额外的子动作,等等。我的解决方案是这样的类:

// MyObj.h
#include <vector>
class MyObj
{
    private:
        std::vector<MyObj*> _children;
    public:
        void addChild(MyObj* m);
}

// MyObj.cpp
#include "MyObj.h"
void MyObj::addChild(MyObj* m)
{
    MyObj::_children.push_back(m);
}

我正在使用这样的类:

MyObj m;
MyObj *child = new MyObj();
m.addChild(child);

我的理解是,由于我在堆上分配了child,所以我需要稍后销毁它。如果创建该对象的代码不维护该引用,则将由父对象来销毁它。像这样定义析构函数是否合适:

MyObj::~MyObj()
{
    for (std::size_t i = 0; i < MyObj::_children.size(); i++)
    {
        delete MyObj::_children[i];
    }
}

我是在正确的轨道上,还是我的方法有缺陷?

PS:如果这是直接重复,我深表歉意,因为我知道已经有很多问题涉及析构函数;我读了一堆,但仍然没有信心。我对 C++ 非常缺乏经验,并且认为直接的问题对我最有帮助。

【问题讨论】:

  • 您应该使用诸如std::unique_ptrstd::shared_ptr 之类的智能指针而不是原始指针来处理对象所有权。作为副作用,您的问题将没有实际意义。
  • 你必须决定你的班级是否拥有它的孩子。如果是这样,那么您将需要执行上面的代码。
  • 我想指出智能指针并不总是能挽救局面。他们带来了他们自己的问题。在决定在整个项目中使用它们之前,请查看 stackoverflow.com/questions/1905787/…
  • 谢谢@Spads。我认为拥有子类对类来说并不是什么大不了的事,因为每个父对象都将在堆栈上声明并最终调用其析构函数。不过,我会研究智能指针;它们是我在学习 C++ 时从未了解过的功能。感谢大家的回复。

标签: c++ class memory-management memory-leaks destructor


【解决方案1】:

除非绝对必要,否则不应使用new。一旦你这样做了,你就有责任释放你动态分配的内存。在上面的代码中:

MyObj m;
MyObj *child = new MyObj();
m.addChild(child);

一旦函数超出范围,mchild 将调用它们的析构函数,因为它们不是动态分配的,因此会破坏它们。

但是,child 指针指向的内容不会以与mchild 类似的方式销毁,因为它是通过new 在空闲存储中动态分配的.在这种情况下,您需要为您放置在免费商店中的每个对象调用delete,就像您在上面所做的那样。

这就是为什么在 cmets 中人们建议您使用智能指针,因为它们遵循 RAII 范式,在这种情况下,一旦超出范围,对象将自动被释放。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-10
    • 2016-01-29
    • 1970-01-01
    • 1970-01-01
    • 2015-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多