用于建模一般树结构的智能指针&它的迭代器

时间:2011-07-13 13:14:11

标签: c++ boost iterator smart-pointers

我通过为每个节点创建一个类来建模一般的树结构,该类具有指向父节点,第一个子节点和第一个兄弟节点的指针,以及指向最后一个兄弟节点的指针(不需要但很有用)。对此,我正在添加一些额外的数据atd。我目前的实施是:

class TreeNode {
    typedef boost::shared_ptr<TreeNode> Ptr;
    typedef boost::weak_ptr<TreeNode> WPtr;

    WPtr p2parent;     ///< pointer to the parent node (NULL in the root)
    Ptr p2sibling;     ///< pointer to the first sibling (or NULL)
    Ptr p2child;       ///< pointer to the first child (or NULL)
    WPtr p2lastChild;  ///< pointer to the last child (not strictly needed)
};

正如您所看到的,我使用shared_ptr作为兄弟和子,因此只需删除它的根就可以删除整个树。对于指向parent的指针,我知道我不应该使用shared_ptr,因为这会创建循环,所以我必须在weak_ptr和原始指针(TreeNode *)之间做出选择 - 任何想法?

对于指向最后一个子节点的(可选)指针,选择在weak_ptr,shared_ptr和原始指针之间 - 为了使整个类内部一致,最佳选择是什么?

最后,我在结构上有几个迭代器,例如深度优先迭代器atd。迭代器应该在内部使用什么指针:raw pointer,weak_ptr或shared_ptr?这三种方法有哪些优点?

2 个答案:

答案 0 :(得分:6)

shared_ptr总是过度杀伤:它是一棵树,所以没有节点的共享所有权。每个节点都有一个所有者:其父级。

如果您使用的实现支持它,则应使用std::unique_ptr作为两个子指针和指向根节点的指针。如果您的实现不支持std::unique_ptr,则可以使用std::auto_ptr,但您需要明确使节点类不可复制。在任何一种情况下,您都可以使用原始指针将指针返回到父级。

(请注意,无论您使用何种类型的指针,您都需要为树类编写复制构造函数和复制赋值运算符:隐式声明的指针不具有正确的语义。)

迭代器只需要一个指向它所指向的元素的原始指针。

答案 1 :(得分:2)

对于父指针:您必须确保它始终指向父级中子项的setter中的实际父级,因此向Treenode析构函数添加unset相对简单。在这种情况下,哑指针会这样做。

对于最后一个孩子指针:要让它保持最新状态还需要做更多的工作,如果你做了那些工作,你会发现你已经涵盖所有情况并且不需要智能任何其他指针。所以哑指针也会在这里做。

你可以使用weak_ptr来获得一些额外的安全性,虽然你应该断言他们没有过期,因为这意味着你忘了取消它们,这可能意味着你没有正确管理它们。

迭代器:应该使用智能指针。

  • 如果他们使用shared_ptr,即使您修改树并断开连接,他们也会保持子树的活动。
  • 如果他们使用weak_ptr,当删除指向的节点时,将使自身无效(您必须检查指针在许多地方仍然有效)。

选择取决于您想要的语义。