【问题标题】:Appropriate use of shared_ptr?适当使用shared_ptr?
【发布时间】:2011-08-06 00:27:51
【问题描述】:

没有使用shared_ptr<> 的经验,我想知道以下是否是合适的用例,以及将shared_ptr<> 返回给用户是否是个好主意。

我有一个类似图形的结构,节点之间有多个连接。在遍历图期间,每个节点都被分配了一个值(从连接的节点计算),我希望用户能够轻松访问该值。整个事情看起来(非常简化)是这样的:

class Pool;
class Node {
    public:
        typedef std::tr1::shared_ptr<Node> Ptr;  
        ...
        void compute_dependencies() { 
            ...
            // calls Pool to get a new Node instance
            dependencies_.push_back(Pool::create_node(...));
            ...
        }

        // evaluate the current node
        void evaluate() { /* use dependencies_ */ };        
        double value() const { if(evaluated) return value_; };

    private:
        std::vector<Node::Ptr> dependencies_;            // vector<Node*> better?
        dbl value_;
}

// Pool creates and owns all nodes
class Pool {
    public:
        static const Node::Ptr create_node(...);         // create a new node
        void traverse_and_evaluate();      

    private:
        std::vector<Node::Ptr> allnodes;   // appropriately sorted to ensure 
                                           // dependencies are evaluated 
        ...
}

用户调用:

Pool pool();
Node::Ptr node1 = Pool::create_node(...);
Node::Ptr node2 = Pool::create_node(...);
....
pool.traverse_and_evaluate();   
// ready to read out the now populated values
cout << node1->value() << " " << node2->value() << ... 

这样做的好处是用户可以直接访问他关心的节点(依赖关系通常是无趣的)。但我不能 100% 确定这是否是个好主意。

感谢您的意见!

编辑:没有循环依赖。

【问题讨论】:

标签: c++ shared-ptr ownership


【解决方案1】:

shared_ptr 主要用于对象没有明确的所有者(或者可能需要比其所有者寿命更长)的时候,因此没有明显的地方可以销毁它。 shared_ptr 本质上成为所有者,当最后一个 shared_ptr 超出范围时,该对象被销毁。

如果你有一个明确的所有者,比如你的 Pool 类,并且没有必要让 Node 对象比拥有 Pool 的对象寿命更长,那么就真的不需要 shared_ptr .您可以在所有者的析构函数中销毁对象。

【讨论】:

  • 谢谢,这让它更清楚了。所以你说的是create_node() 应该返回一个存储在vector&lt;Node*&gt; allnodes 中的原始指针?副本不是一个选项,因为 Node 在创建时不会被评估。
  • @bbtrb:返回 Node* 很好,但我建议使用 std::vector&lt;Node&gt; 代替(没有泄漏)。如果你真的不能复制Node(如果它是一个基类)你可以使用boost::ptr_vector&lt;Node&gt;
  • @bbtrb:是的,返回一个原始指针就足够了。
【解决方案2】:

我喜欢通过weak_ptr提供给其他人的访问,你可以直接从一个shared_ptr构造一个weak_ptr

用户一般会从Pool中获取一个weak_ptr,然后从weak_ptr.lock()构造一个shared_ptr

这向用户传达了他们没有所有权,并且应该注意不要将锁保持的时间超过必要的时间 - 或者至少对我来说是这样的:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-03
    • 2017-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多