【问题标题】:Are data structures an appropriate place for shared_ptr?数据结构是否适合shared_ptr?
【发布时间】:2008-12-17 22:47:35
【问题描述】:

我正在用 C++ 实现二叉树。传统上,我有一个指向左的指针和一个指向右的指针,但手动内存管理通常以泪水告终。这引出了我的问题...

数据结构是否适合使用 shared_ptr?

【问题讨论】:

    标签: c++ data-structures shared-ptr tr1


    【解决方案1】:

    我认为这取决于您将在哪里使用它们。我假设您正在考虑做的事情是这样的:

    template <class T>
    class BinaryTreeNode 
    {
        //public interface ignored for this example
        private:
            shared_ptr<BinaryTreeNode<T> > left;
            shared_ptr<BinaryTreeNode<T> > right;
            T data;
    }
    

    如果您期望您的数据结构能够处理动态创建的节点,这将非常有意义。如果。但是,由于这不是正常的设计,我认为这是不合适的。

    我的回答是,不,这不是使用 shared_ptr 的合适位置,因为 shared_ptr 的使用意味着对象实际上是共享的 - 但是,二叉树中的节点永远不会共享。然而,正如 Martin York 所指出的,为什么要重新发明轮子——已经有一个智能指针类型可以做我们正在尝试做的事情——auto_ptr。所以去吧:

    template <class T>
    class BinaryTreeNode 
    {
        //public interface ignored for this example
        private:
            auto_ptr<BinaryTreeNode<T> > left;
            auto_ptr<BinaryTreeNode<T> > right;
            T data;
    }
    

    如果有人问为什么数据不是 shared_ptr,答案很简单 - 如果数据的副本对库的 client 有好处,他们会传入数据项和树节点制作副本。如果 client 认为复制是一个坏主意,那么 client 代码可以传入一个 shared_ptr,树节点可以安全地复制它。

    【讨论】:

    • 为什么不使用 auto_ptr?您遗漏的公共界面。现在将不可避免地必须包含执行一些内存管理的代码。这就是我们有智能指针的原因,所以我们不需要重新发明轮子来进行内存管理。
    • 好的,auto_ptr 对他们来说是一个有效的选择——事实上,可能会更好,因为它的语义与二叉树节点的左右指针的语义一致。
    • 可能希望将类型 T 传播到您的 left 和 right 声明中,否则不会编译。
    • auto_ptr 自 C++11 起已被弃用,您应该使用 unique_ptr
    【解决方案2】:

    因为左右不共享 boost::shared_ptr 可能不是正确的智能指针。

    这将是一个尝试 std::auto_ptr 的好地方

    【讨论】:

      【解决方案3】:

      是的,绝对的。

      但是如果你有一个循环的数据结构要小心。如果您有两个对象,它们都具有彼此共享的 ptr,那么如果不手动清除共享 ptr,它们将永远不会被释放。在这种情况下可以使用弱 ptr。当然,这对于二叉树来说并不担心。

      【讨论】:

      • 树本质上不是圆形的。
      【解决方案4】:

      在每个对象都有一个所有者的情况下,手动编写内存管理并不是那么困难,因此可以删除它在其析构函数中拥有的内容。

      根据定义,一棵树由节点组成,每个节点都有一个父节点,因此显然是其单一所有者的候选者,这真是一个快乐的时刻。恭喜!

      我认为在您的情况下开发这样的解决方案非常值得*,并且还尝试shared_ptr 方法,将差异完全隐藏在相同的界面后面,因此您可以在两者之间切换并比较性能差异一些现实的实验。这是了解shared_ptr 是否适合您的应用程序的唯一可靠方法。

      (*对我们来说,如果你告诉我们进展如何。)

      【讨论】:

        【解决方案5】:

        永远不要将 shared_ptr 用于数据结构的节点。如果在任何时候共享所有权,它可能会导致节点的销毁被暂停或延迟。这可能会导致以错误的顺序调用析构函数。 在数据结构中,节点的构造函数包含与其他节点耦合的任何代码,而析构函数包含与其他节点分离的代码,这是一种很好的做法。以错误顺序调用的析构函数可能会破坏这种设计。

        【讨论】:

          【解决方案6】:

          shared_ptr 有一些额外的开销,特别是在空间要求方面,但如果您的元素是单独分配的,那么 shared_ptr 将是完美的。

          【讨论】:

            【解决方案7】:

            你甚至需要指针吗?看来你可以使用boost::optional&lt;BinaryTreeNode&lt;T&gt; &gt; left, right

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-05-09
              • 2011-01-13
              • 2014-06-18
              相关资源
              最近更新 更多