假设我有一个二叉树类,其目的是将真实区间 (a, b) 归纳为许多小区间,并选取中点。注意:我实际上正在写的课程涉及平面上的三角形,但想法是一样的。
这是该类在头文件中的样子:
class Tree
{
public:
Tree(double &a, double &b, int depth);
~Tree();
Tree getCopy() const;
private:
Tree(double *a, double *b, int depth, int maxDepth);
double *a, *b;
int depth, maxDepth;
Tree *leftChild, *rightChild;
};
请注意,树存储指向双精度数 a 和 b 的指针,而不是实际双精度数。这样做的原因是为了节省内存(和速度?),观察到 a 和 b 将被许多子树共享(我知道双倍是相当“轻”的,但在我的实际课堂上,我有一些“更重”)。
现在这里是主要的构造函数:
Tree::Tree(double *a, double *b, int depth, int maxDepth) :
depth(depth), maxDepth(maxDepth)
{
if (depth == maxDepth)
{
this->a = new double(*a);
this->b = new double(*b);
}
else
{
this->a = a;
this->b = b;
}
if (depth == 0)
{
leftChild = 0;
rightChild = 0;
}
else
{
double * midpoint = new double((*a+*b)/2);
leftChild = new Tree(a, midpoint, depth - 1, maxDepth);
rightChild = new Tree(midpoint, b, depth - 1, maxDepth);
}
}
和析构函数:
Tree::~Tree()
{
if (depth == 0)
{
delete b;
}
else
{
delete leftChild;
delete rightChild;
}
if (depth == maxDepth)
{
delete a;
}
}
我希望这两个功能都是正确的。请注意,构造函数是私有的,它是递归调用的。公共构造函数如下:
Tree::Tree(double &a, double &b, int depth)
{
*this = *(new Tree(&a, &b, depth, depth));
}
我知道这看起来很奇怪,我担心这样做可能会造成内存泄漏?但另一方面,如果我写:
*this = Tree(&a, &b, depth, depth);
那不会失败吗?让我尝试通过考虑等效函数来解释为什么我认为它可能会失败
{
Tree T(&a, &b, depth, depth);
*this = T;
}
我在想,一旦退出此函数,对象 T 就会被销毁,因此子项会被删除等。
复制功能也有同样的问题:
Tree Tree::getCopy() const
{
return Tree(a, b, depth, depth);
}
所以问题是:编写这些函数的正确方法是什么?我也愿意听取关于我写这门课的方式的一般评论。提前致谢!