【问题标题】:N-Ary Tree Design with Smart Pointers带智能指针的 N​​ 叉树设计
【发布时间】:2012-08-21 12:39:15
【问题描述】:

我正在尝试用 C++ 设计一个树类,但在节点破坏方面遇到了一些麻烦。

如果我销毁一个节点,我不想销毁它的整个子树,因为可能有其他东西指向它。所以显而易见的解决方案是使用引用计数。我有一个指向父节点的弱指针,以及一个指向子节点的共享指针向量。这样,如果一个节点被销毁,它的子节点只有在没有指向它们的情况下才会被销毁。

但我在这里遇到了另一个问题:向节点添加子节点。 weak_ptr 仅在已经存在指向对象的 shared_ptr 时才有效。如果我将一个子节点添加到一个节点,我不知道在哪里可以找到指向它的 shared_ptr。那我在这里做什么呢?

【问题讨论】:

  • 每个孩子都有父母吗?
  • 每个孩子都有一个父成员,但根没有父成员。
  • 我的意思是逻辑上,而不是代码上。每个孩子都有会员吗?如果是这样,那么在您的实现中,每个孩子都已经存在于其父母的孩子的向量中,因此您可以从中获取共享指针。 (虽然我没有 100% 理解为什么你首先需要共享所有权......)
  • @KerrekSB:虽然这可能是真的,但在添加节点时需要在层次结构中向上走两级(如果父节点不是根节点,则必须特殊情况)然后遍历子元素列表,直到找到指向挂起新元素的节点的智能指针。
  • 如果我的代码中已经有一个引人注目的用例,我真的只会实现它。我还没有看到销毁节点而不是其子树的情况会很有意义。无论如何,这对子树意味着什么?所有的孩子都会成为根吗?

标签: c++ tree smart-pointers


【解决方案1】:

您可能想查看enable_shared_from_this,它允许您直接从对象中获取shared_ptr。它仍然要求该对象由shared_ptr 管理,但您不需要找到持有它的人。

【讨论】:

  • 好的,但是根目录呢?等等,我可以让 Tree 类持有一个指向根的共享指针。我们很好!
  • @Avi: 有两种选择:要么root由shared_ptr管理(在这种情况下你很好),或者不是,在这种情况下你无法获得weak_ptr它。我的建议是还通过shared_ptr 管理root。在大多数设计中,所有节点都是它们自己子树的根,从这个角度来看,根不应与任何其他节点有任何不同,因此如果所有节点都由shared_ptr 管理,那么根节点也应如此。
  • 是的,我现在看到这可能是必要的:创建新子代时,您需要一个weak_ptr 指向父代,而不仅仅是一个原始指针,所以shared_from_this(或weak_from_this? ) 将是必要的。
  • @Avi:请注意,可能还有其他选择,例如,将 weak_ptr/shared_ptr 传递给父级到子级的构造函数。毕竟,在将其插入给定位置之前,您必须找到它......所以您已经拥有该信息。将父级传递给子级的构造函数可能是一个好方法。
【解决方案2】:

为了扩展 David Rodriguez 的想法,骨架树可能如下所示:

struct node : std::enable_shared_from_this<node>
{
    std::vector<std::shared_ptr<node>> children;
    std::weak_ptr<node> parent;

    void add_child()
    {
        auto n = std::make_shared_node>();
        n->parent = std::weak_ptr<node>(shared_from_this());
        children.emplace_back(n);
    }
}

auto root = std::make_shared<node>();

root.add_child();
root.add_child();
root.add_child();

root.children[0].add_child();

(当然,现实世界中的node 将有一个具有有效负载值的非平凡构造函数,而add_child 将采用类似的参数或作为模板......)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-24
    • 2018-01-20
    • 2020-03-01
    • 1970-01-01
    • 2021-12-15
    • 2015-10-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多