With no experience with shared_ptr<>
I am wondering whether the following is an appropriate use case and also whether it is a good idea to return shared_ptr<>
to the user.
I have a graph like structure with multiple connections between the nodes. During traversal of the graph each node is assigned a value (computed from connected nodes) and I want the user to be able to access the value easily. The whole thing looks (strongly simplified) like this:
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
...
}
and the user calls:
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() << ...
This has the benefit that the user gets directly access to the nodes he cares about (dependencies are often uninteresting). But I'm not 100% sure whether this is a good idea.
Thanks for your input!
Edit: There are no circular dependencies.
shared_ptr
is primarily useful for times when an object doesn't have a clear-cut owner (or maybe needs to outlive its owner), so there's no obvious place to destroy it. The shared_ptr
essentially becomes the owner, and the object is destroyed when the last shared_ptr
to it goes out of scope.
When you've got a clear owner, like your Pool
class, and there's no need for the Node
objects to outlive the owning Pool
, then there really isn't much need for a shared_ptr
. You can just destroy the objects in the owner's destructor.
I like to provide access to others via weak_ptr, you can construct a weak_ptr< Node > directly from a shared_ptr< Node >.
The user would generally retrieve a weak_ptr from the Pool and then construct a shared_ptr< Node > from the weak_ptr< Node >.lock().
This conveys to the user they don't have ownership rights, and should be careful not to maintain the lock longer than is necessary - or at least it does to me :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With