bolov
bolov

Reputation: 75924

Smart pointer for single owner and multiple references

Back in the days I implemented linked lists and trees using raw pointers. When I tried to implement using smart pointers I came upon the following problem as I don’t know what to use for a pointer that will have only one owner but 0 or more references:

For an example lets take a binary tree:

For starters the nodes should be the only ‘owners’ of the pointers: the nodes live and die with the tree, so to me it makes sense to make them unique_ptr and not shared_ptr:

class Tree {
  std::unique_ptr<Node> root_;
}

class Node {
  std::unique_ptr<Node> left_child_, right_child_;
}

And then I had to make an algorithm like that:

Node * node = root_.get(); // <-- what type should node be??
while(node) {
  if (node->left_count < node->right_count) {
    node = node->left_child_.get();
  } else {
    node = node->right_child.get();
  }
}
// do something on node

But I don’t like using raw pointers. So what kind of smart pointer node should be? The idea is that it should have no ownership over the pointer. I read that weak_ptr — which looks like what I want — works only with shared_ptr, but again I think that there is no need of the overhead of shared_ptr here. At any point in time there will be one and only one owner.

Along the same lines for a linked list:

class LinkedList {
  std::unique_ptr<Node> first_;
  /** ?? type ?? **/ last_;
}


for (/*?? type ??*/ n = first_; n != last_; n = n->next) {
}

edit

The reason why I don’t like using raw pointers (beyond the point of not using them anymore in C++) is let’s say I want to expose them to the outside (via interface): it should be clear that they should not be freed. A smart pointer should be the smart choice here.

Upvotes: 4

Views: 707

Answers (1)

Rog&#233;rio Ramos
Rog&#233;rio Ramos

Reputation: 286

Maybe you are over engineering here. It should be fine that the external clients consume a raw pointer as long as they respect the fact they are not involved in the object lifetime. If you really want to be purist then you would need to use shared_ptr and return weak_ptr. Notice that you might actually need to do anyway that because in order to construct or maintain your data structure the internal pointer might need to be shared temporarily.

Another option is to use unique_ptr in the data structure and create your own custom smart pointer that consumes the raw pointer returned by unique_ptr::get. I think a good name would be proxy_ptr and could even have something like: proxy_ptr p = make_proxy(yourUniquePtr.get());

Upvotes: 3

Related Questions