Class 成员函数正常工作,但在作为另一个 class 的数据成员调用时陷入死循环

Class member function works normally, but gets stuck in an infinite loop when called as a data member of another class

我写了一个树结构,并做了一个基本的搜索功能来寻找树中的节点。树本身使用哨兵节点来标记所有端点(根的父节点,叶子的子节点),并且搜索简单地遍历节点,直到找到匹配项或命中哨兵节点。当我在树的实例上调用搜索功能时,它工作正常,但是当树是另一个 class 的数据成员时,它会卡住。在下面的代码中,"t.search(1)" 有效,但 "embedded_tree.t.search(1)" 陷入无限循环。

我已经将其缩小到这样一个事实,即当调用 embedded_tree.t.search() 时,“&sentinel”的内容正确地指向了 sentinel 节点,但似乎是一个新指针,因为它不等同于 root、sentinel.parent 和 sentinel.child 的内容。从这里我被卡住了,我不确定如何调用它,以便 &sentinel 匹配构建树时创建的指针。

#include <iostream>

struct NODE {
    int key;
    NODE* parent;
    NODE* child;
    NODE() : key(0), parent(NULL), child(NULL) {};
};

struct TREE {
    NODE sentinel;
    NODE* root;

    TREE()
    {
        sentinel = *new NODE;
        sentinel.parent = &sentinel;
        sentinel.child = &sentinel;
        root = &sentinel;
    }

    NODE* search(int k)
    {
        NODE* x = root;
        while (x != &sentinel)
        {
            if (x->key == k) return x;
            x = x->child;
        }
        return &sentinel;
    }
};

struct A {
    TREE t;

    A() : t(*new TREE()) {};
};

int main()
{
    TREE t;
    t.search(1);

    A embedded_tree;
    embedded_tree.t.search(1);
}

您将动态内存分配与堆栈分配混淆了。当你做

sentinel = *new NODE

不好的事情发生了。在堆栈上为 NODE sentinel 分配内存,然后在 new 运算符中为 NODE 分配内存,然后分配给 sentinel 变量,并在 new 运算符中创建内存丢失了。你应该重写你的代码来使用指针,并添加析构函数,像这样

#include <iostream>

struct NODE {
    int key;
    NODE* parent;
    NODE* child;
    NODE() : key(0), parent(NULL), child(NULL) {};
};

struct TREE {
    NODE* sentinel;
    NODE* root;

    TREE()
    {
        sentinel = new NODE;
        sentinel->parent = sentinel;
        sentinel->child = sentinel;
        root = sentinel;
    }

    ~TREE() {
        if (NULL != sentinel) {
            delete sentinel;
            sentinel = NULL;
            root = NULL;
        }
    }

    NODE* search(int k)
    {
        NODE* x = root;
        while (x != sentinel)
        {
            if (x->key == k) return x;
            x = x->child;
        }
        return sentinel;
    }


};

struct A {
    TREE* t;

    A() : t(new TREE()) {};
    ~A() {
        if (NULL != t) {
            delete t;
            t = NULL;
        }

    }
};

int main()
{
    TREE t;
    t.search(1);

    A embedded_tree;
    embedded_tree.t->search(1);
}

但是,既然我们在谈论 C++,我建议您在熟悉手动内存管理之后再看看智能指针和容器。