2011-04-15 76 views
8

没有shared_ptr<>的使用经验我想知道以下是否是适当的用例,以及是否将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%确定这是否是一个好主意。

感谢您的输入!

编辑:没有循环依赖关系。

+0

你可能会发现这个问题和答案有点相关:http://stackoverflow.com/questions/5629592/resource-leak-during-object-creation-c/ – Anton 2011-04-15 03:05:12

回答

10

shared_ptr是次主要有用当一个物体没有一个明确的拥有者(或者可能需要活过它的主人)时,所以没有明显的地方来销毁它。 shared_ptr实质上成为所有者,并且当最后的shared_ptr超出范围时,该对象被销毁。

当你有一个明确的所有者,就像你Pool类,并没有必要为Node对象活得比所属Pool,那确实不是一个shared_ptr太大必要。你可以销毁所有者的析构函数中的对象。

+0

谢谢,这使得它相当更清楚一点。所以你说的是'create_node()'应该返回存储在'vector allnodes'中的原始指针?副本不是一个选项,因为在创建时不会评估“节点”。 – bbtrb 2011-04-15 03:28:39

+3

@bbtrb:返回一个'Node *'很好,但我会建议使用'std :: vector '而不是泄漏。如果你真的不能复制'Node'(如果它是一个基类),你可以使用'boost :: ptr_vector '。 – 2011-04-15 06:47:19

+0

@bbtrb:是的,返回一个原始指针就足够了。 – 2011-04-15 15:05:48

3

我喜欢通过weak_ptr提供对他人的访问,您可以直接从shared_ptr < Node>构造一个weak_ptr < Node>。

用户通常会从Pool中检索一个weak_ptr,然后从weak_ptr < Node> .lock()构造一个shared_ptr < Node>。

这传达给他们没有所有权的用户,并应注意不要保持锁超过所需的时间 - 至少它给我:)