Reputation: 1023
I am trying to implementing a SegmentTree
class to be used in another Solution
class.
In class SegmentTree
, the destructor is implemented as follows:
~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 {
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:
tree
pointer in Solution
class?Upvotes: 2
Views: 937
Reputation: 595305
Do we need to implement destructor to delete
tree
pointer inSolution
class?
If you use new
to create an object, you need to delete
the object when you are done using it. 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).
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:
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:
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:
class Solution {
private:
SegmentTree tree;
public:
Solution(vector<int>& nums) :
tree(nums)
{
}
};
Upvotes: 5
Reputation: 122133
There must be exactly one delete
for every new
or there will be a memory leak. 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. For example copying the above Solution
will cause problems (because the compiler generated assignment and copy constructor aren't doing the right thing). When possible you should strive to follow the rule of 0, for example by not using a pointer in the first place:
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.
Upvotes: 4