简体   繁体   English

另一个类中的类对象的 C++ 析构函数

[英]C++ destructor for class object within another class

I am trying to implementing a SegmentTree class to be used in another Solution class.我正在尝试实现要在另一个Solution类中使用的SegmentTree类。

In class SegmentTree , the destructor is implemented as follows:class SegmentTree ,析构函数实现如下:

~SegmentTree() {
    destruct(root);
};

void destruct(Node* root) {
    if (!root) return;
    
    destruct(root->left);
    destruct(root->right);
    delete root;
    root = NULL;
}

Then, in class Solution , we have然后,在class Solution ,我们有

class Solution {
private:
    SegmentTree* tree;

public:
    Solution(vector<int>& nums) {
        tree = new SegmentTree(nums);
    }

    //Question: how shall ~Solution() be implemented to free memory of the pointer tree?
};

The question:问题:

  1. Do we need to implement destructor to delete tree pointer in Solution class?我们是否需要实现析构函数来删除Solution类中的tree指针?
  2. If yes, how shall that be implemented?如果是,将如何实施?

There must be exactly one delete for every new or there will be a memory leak.每个new的都必须有一次delete ,否则就会出现内存泄漏。 You can write a destructor like this:你可以写一个这样的析构函数:

class Solution {
private:
    SegmentTree* tree;

public:
    Solution(vector<int>& nums) {
        tree = new SegmentTree(nums);
    }
    ~Solution() { 
        delete tree;
    }
};

However, you need to read about the rule of 3/5 ( What is The Rule of Three? ), because when a class manages a resource a constructor and destructor are not sufficient.但是,您需要阅读 3/5 规则( 什么是三的规则? ),因为当一个类管理资源时,只有构造函数和析构函数是不够的。 For example copying the above Solution will cause problems (because the compiler generated assignment and copy constructor aren't doing the right thing).例如复制上述Solution会导致问题(因为编译器生成的赋值和复制构造函数没有做正确的事情)。 When possible you should strive to follow the rule of 0, for example by not using a pointer in the first place:如果可能,您应该努力遵循 0 规则,例如首先不使用指针:

class Solution {
private:
    SegmentTree tree;

public:
    Solution(vector<int>& nums) : tree(nums) {}
};

If the member must be dynamically allocated you should use a std::unique_ptr (and again rule of 0) but never a raw pointer.如果必须动态分配成员,则应使用std::unique_ptr (并且再次使用 0 规则)但不要使用原始指针。

Do we need to implement destructor to delete tree pointer in Solution class?我们是否需要实现析构函数来删除Solution类中的tree指针?

If you use new to create an object, you need to delete the object when you are done using it.如果使用new创建对象,则需要在使用delete该对象。 So yes, Solution needs a destructor to delete the tree that it new 's (just as SegmentTree needs a destructor to delete the Node 's that it new 's).所以是的, Solution需要一个析构函数来deletenewtree (就像SegmentTree需要一个析构函数来deletenewNode )。

If yes, how shall that be implemented?如果是,将如何实施?

Like this:像这样:

class Solution {
private:
    SegmentTree* tree;

public:
    Solution(vector<int>& nums) :
        tree(new SegmentTree(nums))
    {
    }

    ~Solution() {
        delete tree;
    }
};

Which you can automate by using std::unique_ptr , eg:您可以使用std::unique_ptr自动化,例如:

class Solution {
private:
    std::unique_ptr<SegmentTree> tree;

public:
    Solution(vector<int>& nums) :
        tree(std::make_unique<SegmentTree>(nums))
        //tree(new SegmentTree(nums))
    {
    }
};

Either way, do be aware of the Rule of 3 :无论哪种方式,请注意3 规则

If a class requires a user-defined destructor, a user-defined copy constructor, or a user-defined copy assignment operator, it almost certainly requires all three.如果一个类需要一个用户定义的析构函数、一个用户定义的复制构造函数或一个用户定义的复制赋值运算符,它几乎肯定需要所有这三个。

So, you should also implement (or disable) the copy constructor and copy-assignment operator, eg:因此,您还应该实现(或禁用)复制构造函数和复制赋值运算符,例如:

class Solution {
private:
    SegmentTree* tree;

public:
    Solution(vector<int>& nums) :
        tree(new SegmentTree(nums))
    {
    }

    Solution(const Solution &src) :
        tree(new SegmentTree(*(src.tree)))
    {
    }

    ~Solution() {
        delete tree;
    }

    Solution& operator=(const Solution &rhs) {
        if (&rhs != this) {
            Solution tmp(rhs);
            std::swap(tree, tmp.tree);
        }
        return *this;
    }
};

Though, you might consider simply getting rid of new to begin with and just let the compiler manage the SegmentTree object for you:不过,您可能会考虑简单地摆脱new开始,让编译器为您管理SegmentTree对象:

class Solution {
private:
    SegmentTree tree;

public:
    Solution(vector<int>& nums) :
        tree(nums)
    {
    }
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM