复制构造函数和析构函数八叉树c++

Copy constructor and destructor octree c++

本文关键字:八叉树 c++ 析构函数 构造函数 复制      更新时间:2023-10-16

我已经创建了一个八叉树数据结构,但它还不完美。我一直在为复制构造函数和析构函数而苦恼。这是我的头文件:

class Octree
{
public:
static int lastbranch;
static bool utolsoelotti;
struct node
{
    int value;
    node *child[8];
};
Octree();
~Octree();
Octree(const Octree& oct);
void clear(node* node);
node* searchandset(int dec, int value);
node* search(int dec);
node* step(node *node, int k);
node* copy(node *n);
void Print(node *n)const;
void deletebranch(int branch);
node *root;
};

构造函数、析构函数、复制控制器

Octree::Octree()
{
root = new node;
root->value = 0;
for (int i = 0; i < 8; i++)
    root->child[i] = 0;
}
Octree::~Octree()
{
clear(root);
}
Octree::Octree(const Octree& oct) {
root = copy(oct.root);
}
void Octree::clear(node *node){
    for (int i = 0; i < 8; i++)
        if (node->child[i])
            clear(node->child[i]);
    delete node;
}
Octree::node*Octree::copy(node *n) {
node* n2 = new node;
if (n) {
    for (int i = 0; i < 8; i++) {
        n2->child[i] = copy(n->child[i]);
    }
}
return n2;
}

以下是我主要如何创建对象:

int main() {
Octree tree;
Octree tree2(tree);
tree.searchandset(8, 2);
tree2.Print(tree2.search(8));
return 0;
}

searchandset函数中,我为第一棵树上的节点编号8给定一个值。之后,我调用复制构造函数并打印第二个树的第8个节点。这个值与我为第一棵树给出的值相同,但当解构造器调用时,我总是得到这个异常:

引发异常:读取访问冲突。节点为0xDDDDDDDD。

正如我所知,这意味着我试图删除我已经删除的节点。对象"tree2"与具有相同值和节点的"tree"是不同的对象,不是吗?那么我不理解上面的例外情况。我是c++的新手,我知道这是基本的东西,所以如果有人能引导我朝着正确的方向前进,我会非常感激。

问题出在copy函数中。让我们一步一步地进行:

node* n2 = new node;
if (n) {
    for (int i = 0; i < 8; i++)
        n2->child[i] = copy(n->child[i]);
}
return n2;

对于使用默认构造函数构造并复制到另一个Octree:的空Octree oct

  1. 创建一个新的noden2
  2. noctroot,因此条件为true
  3. n2child[i]具有对应子级的copy的值,因此再次调用copy
  4. 创建新节点n2
  5. nnullptr(因为oct中的所有nullptr都是子级),所以不执行条件
  6. 返回n2
  7. 重复步骤36 8次
  8. 返回根n2
  9. 将新指针(n2)分配给复制对象的root

但是等一下!您注意到了吗,在步骤6中,您正在return中创建一个新指针,尽管子指针应该是nullptr

这就是问题所在,因为在clear中,您将遍历每个子级。还是可以的,对吧?但是,您尝试访问未初始化的子级(它们具有随机值,条件将计算为true),因此您得到了Read access violation,因为它不是您的内存。

那么解决方案?如果n不是nullptr,则仅为n2分配内存。