C++ 在递归函数中创建std::值列表而不是std::指针列表

C++ 在递归函数中创建std::值列表而不是std::指针列表,c++,pointers,recursion,c++11,C++,Pointers,Recursion,C++11,我有这门课: class obj { public: obj() : parent(nullptr), depth(0) { } obj* parent; list<obj> children; int depth; // Used only for this example }; 以这种方式,例如: obj root; recursive(root); 如果您注意,您可以看到,如果递归函数中的测试

我有这门课:

class obj
{
public:

    obj()
        : parent(nullptr),
        depth(0)
    {   }

    obj* parent;
    list<obj> children;
    int depth;  // Used only for this example
};
以这种方式,例如:

obj root;
recursive(root);
如果您注意,您可以看到,如果递归函数中的测试是:

if(parent.depth == n)
    return;
当n>=2时,此代码将不起作用。一旦退出递归函数,孙子根->子->子的父级存储地址将不是有效地址

解决此问题的一种方法是使用指针列表子项而不是值列表:

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);
}

是否有另一种方法来执行相同的工作并将对象存储在一个值列表中而不是在指针列表中?

您可以考虑在Objs中存储唯一的ID,这样OBJ的实例不定义所代表的对象的身份,而是它的ID。如果这样做,您可能会将ID存储到链接相关的OBJ,而不是存储指针

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

当您想要跟随链接时,这需要更多的工作:您不需要跟随指向父对象的指针,而是需要在您维护的某个全局对象列表中查找该对象,以搜索相关的parentId


当然,这取决于这些对象真正代表的是什么,以及你要完成的更广泛的目标……/P> < P>你可以考虑在Objs中存储唯一的ID,这样OBJ的实例不定义所代表的对象的身份,而是它的ID。如果这样做,您可能会将ID存储到链接相关的OBJ,而不是存储指针

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

当您想要跟随链接时,这需要更多的工作:您不需要跟随指向父对象的指针,而是需要在您维护的某个全局对象列表中查找该对象,以搜索相关的parentId


当然,这实际上取决于这些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);
}

在开始创建更多的子对象之前,这不是一个修复对象地址的问题吗?要做到这一点,首先将它们放入子列表,然后递归

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);
}

对不起,我不明白你的意思,你能给我举个例子吗?@Nick我提供了更多的细节,但让它相当抽象。这有用吗?嗯。。。我不认为你的回答能帮我列出价值清单:@Nick你怎么会这么想?我的回答解决了关于无效对象指针损坏的问题——根据我的建议,您不会有指针,因此不会有任何损坏。也许我没有解释得很好,如果你认为…尝试用C++来代替英语,也许这能帮助我。对不起,我不明白你的意思,你能给我一个例子吗?这有用吗?嗯。。。我不认为你的回答能帮我列出价值清单:@Nick你怎么会这么想?我的回答解决了关于无效对象指针损坏的问题——根据我的建议,您不会有指针,因此不会有任何损坏。也许我没有解释得很好,如果你认为……尝试用C++来代替英语,也许这能帮上忙。是的,这是一个有效的答案+ 1,但是我现在不能改变我的指令的顺序。”Nick:告诉我们你不能做这样的事情,而不解释为什么很难提出解决方案。尽管如此,从您的角度来看,我还是会抛出另一个可能会重新排序,也可能不会重新排序的参数:您可以在递归中省略设置son.parent,而是使用一个额外的函数参数来计算深度,在每个递归调用中添加1,然后使用第二个函数,该函数返回结构并在递归解缠后填充.parent指针,将值复制到它们的最终列表位置。请耐心等待。。。我正在尽我最大的努力使用真正的代码,它有点复杂。。。如果我可以用您的解决方案调整代码,我会将其标记为答案。是的,这是一个有效的答案+1,但我现在不能更改指令的顺序。@Nick:告诉我们,如果不解释原因,您就不能这样做,这会使提出解决方案变得非常困难。尽管如此,从您的角度来看,我还是会抛出另一个可能会重新排序,也可能不会重新排序的参数:您可以在递归中省略设置son.parent,而是使用一个额外的函数参数来计算深度,在每个递归调用中添加1,然后使用第二个函数,该函数返回结构并在递归解缠后填充.parent指针,将值复制到它们的最终列表位置。请耐心等待。。。我正努力用真正的代码做到最好
至少有点复杂。。。如果我可以用你的解决方案调整我的代码,我会标记为答案。你可以使用工厂创建对象吗?这是一个很好的解决方案。拥有一个工厂对象,该对象创建OBJ,并将每个对象的内部唯一ID映射到其当前指针。每个obj都可以保留对factory对象的引用,并且在复制构造函数期间告诉factory新地址并使旧地址无效。然后你可以保留一个父ID,并在需要时向工厂索要它的指针。我认为我不能使用,但我不确定,因为我以前从未使用过工厂。。。无论如何谢谢你!尼克:你不知道怎么做,有人建议做一些听起来很有前途的事情,说我不认为我能用它[因为我以前没有做过]/无论如何,谢谢,这真的是一种解雇、不感激和适得其反的行为——如果你以前解决过这个问题,你现在就不会问了。你为什么不为你的麻烦说声对不起,但我不知道如何实施你的建议,你能给我多一点帮助吗?就目前而言,这个问题是不明确的。我们不知道你为什么要这么做。我们不知道需求——什么可以改变,什么不能。如果你澄清这个问题,我可以举一个简短的例子,但在此之前,我不会猜测什么是可行的,什么是不可行的。你可以使用工厂来创建对象吗?这是一个简单的例子。拥有一个工厂对象,该对象创建OBJ,并将每个对象的内部唯一ID映射到其当前指针。每个obj都可以保留对factory对象的引用,并且在复制构造函数期间告诉factory新地址并使旧地址无效。然后你可以保留一个父ID,并在需要时向工厂索要它的指针。我认为我不能使用,但我不确定,因为我以前从未使用过工厂。。。无论如何谢谢你!尼克:你不知道怎么做,有人建议做一些听起来很有前途的事情,说我不认为我能用它[因为我以前没有做过]/无论如何,谢谢,这真的是一种解雇、不感激和适得其反的行为——如果你以前解决过这个问题,你现在就不会问了。你为什么不为你的麻烦说声对不起,但我不知道如何实施你的建议,你能给我多一点帮助吗?就目前而言,这个问题是不明确的。我们不知道你为什么要这么做。我们不知道需求——什么可以改变,什么不能。如果你澄清这个问题,我可以举一个简短的例子,但在此之前,我不会猜测什么是可行的,什么是不可行的。
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);
}
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);
}