在递归函数中创建 std::list of value 而不是 std::list of 指针

Create std::list of value instead of std::list of pointers in recursive function

本文关键字:of std list 指针 value 递归函数 创建      更新时间:2023-10-16

我有这个类:

class obj
{
public:
    obj()
        : parent(nullptr),
        depth(0)
    {   }
    obj* parent;
    list<obj> children;
    int depth;  // Used only for this example
};

为了填充我的数据结构,我使用如下所示的递归函数:

void recursive(obj& parent)
{
    if(parent.depth == 1)
        return;
    obj son;
    son.parent = &parent;
    son.depth = parent.depth + 1;
    recursive(son);
    parent.children.push_back(son);
}

例如,以这种方式:

obj root;
recursive(root);

如果你注意的话,你可以看到,如果递归函子中的测试是:

if(parent.depth == n)
    return;

有了n >= 2,这段代码将不起作用(一旦退出递归函数,"孙子"root->son->son父级的存储地址 - 依此类推 - 将不是有效的地址)。

解决此问题的一种方法是使用指针列表(list<obj*> children)而不是值列表:

void recursive(obj& parent)
{
    if(parent.depth == 2)
        return;
    obj* son_ptr = new obj();
    son_ptr->parent = &parent;
    son_ptr->depth = parent.depth + 1;
    recursive(*son);
    parent.children.push_back(son_ptr);
}

有没有另一种方法可以做同样的工作并将obj存储在值列表中而不是指针列表中?

在开始创建更多子对象之前,这不就是修复对象的地址吗? 为此,请先将它们放入子列表,然后递归...

void recursive(obj& parent, int n)
{
    if (parent.depth == n)
        return;
    obj son;
    son.parent = &parent;
    son.depth = parent.depth + 1;
    parent.children.push_back(son);
    recursive(parent.children.back(), n);
}

您可以考虑在 obj 中存储唯一 ID,这样obj的实例不会定义所表示对象的标识,而是定义其 ID 的标识。如果这样做,则可能会存储 ID 以链接相关obj,而不是存储指针。

例如,您可以更改obj类以包含int字段id

class obj {
public:
    obj()
        : parent(nullptr),
          depth(0)
    {
        // Not thread-safe; would need to get protected if multi-threaded
        id = nextId++;
    }
    static int nextId;
    int id;
    int parentId;
    list<int> childrenIds;
    int depth;  // Used only for this example
};

每当构造新obj来表示新的逻辑"事物"时,都可以为id字段分配一个新的唯一值。当您想要在表示相关"事物"的obj之间建立关系时,例如,您可以使用parentId字段而不是parent指针字段:

void recursive(obj& parent)
{
    if (parent.depth == 1) {
        return;
    }
    obj son;
    son.parentId = parent.id;
    son.depth = parent.depth + 1;
    recursive(son);
    parent.childrenIds.push_back(son.id);
}

当您想要访问链接时,这需要更多的工作:而不是跟随指向父obj的指针,而是需要在您维护的某个全局obj列表中查找obj(搜索有问题的parentId)。

当然,这实际上取决于这些obj真正代表什么,以及您要实现的更广泛目标......