shared_ptr的适当使用方法是什么?

8

我对 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() << ... 

这样做的好处是用户可以直接访问他关心的节点(依赖关系通常不重要)。但我不确定这是否是一个好主意。感谢您的反馈!编辑:没有循环依赖。

您可能会发现这个问题和答案有些相关:http://stackoverflow.com/questions/5629592/resource-leak-during-object-creation-c/ - Anton
2个回答

10

shared_ptr 主要用于当对象没有明确的所有者(或者可能需要超出其所有者的生命周期),因此没有明显的位置来销毁它时。 shared_ptr 实际上变成了所有者,当最后一个指向该对象的 shared_ptr 超出作用域时,对象会被销毁。

当你拥有一个明确的所有者,比如你的 Pool 类,并且不需要 Node 对象超出所属的 Pool 的生命周期时,就没有太多需要使用 shared_ptr 的必要性。你可以在所有者的析构函数中直接销毁这些对象。


谢谢,这使得问题更加清晰了。所以您的意思是 create_node() 应该返回一个原始指针,它将被存储在 vector<Node*> allnodes 中?由于 Node 在创建时未被评估,因此复制不是一个选项。 - bbtrb
3
返回一个 Node* 是可以的,但我建议使用一个 std::vector<Node> 代替(避免内存泄漏)。如果你真的不能复制 Node (如果它是一个基类),你可以使用 boost::ptr_vector<Node> - Matthieu M.
@bbtrb:是的,返回一个原始指针就足够了。 - Head Geek

3
我喜欢通过weak_ptr为其他人提供访问权限,您可以直接从shared_ptr<Node>构造weak_ptr<Node>。
用户通常会从池中检索weak_ptr,然后从weak_ptr<Node>.lock()构造shared_ptr<Node>。
这向用户传达了他们没有所有权,并且应该小心不要保持锁的时间比必要的时间长 - 至少对我来说是这样的 :)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接