14

I'd like to wrap raw pointer member to some smart pointer to prevent deleting inside a developing class. Owner of the object under pointer is outside of class. So, looks like boost::shared_ptr and std::auto_ptr does not fit. The following is a reduced example:

class Foo {
  boost::weak_ptr<Bar> m_bar;
public:
  void setBar(const Bar *bar) { // bar created on heap
    m_bar = bar;                // naturally compilation error
  }
};

Of course, it induces compilation error. What is a correct way to initialize weak_ptr from a raw pointer (if exist)?

Loom
  • 9,768
  • 22
  • 60
  • 112
  • possible duplicate of [shared\_ptr & weak\_ptr conversions](http://stackoverflow.com/questions/17522020/shared-ptr-weak-ptr-conversions) – CS Pei Oct 02 '13 at 15:08
  • 1
    If you want to prevent deletion of that pointer within your class then don't call `delete` on it, and don't provide accessor functions that expose the pointer to clients. `weak_ptr` is meant for non-owning view of an object owned by a `shared_ptr`. If you were able to somehow stuff that pointer into a `weak_ptr` it'd have no idea whether the pointer has expired, nor does it prevent me from calling `delete m_bar.lock().get();` within your class. You can never make everything 100% idiot-proof. – Praetorian Oct 02 '13 at 15:13

5 Answers5

16

You can't do that, you can only create a weak_ptr out of a shared_ptr or another weak_ptr. So the idea would be that the owner of the pointer hold a shared_ptr instead of a raw pointer, and everything should be ok.

Julien Lopez
  • 1,021
  • 6
  • 14
11

The only way to do it is by getting hold of a shared_ptr or weak_ptr that owns the pointer, otherwise the weak_ptr has no way to find the existing owner in order to share ownership with it.

The only way to get a shared_ptr from a raw pointer that is already owned by another shared_ptr is if Bar derives from enable_shared_from_this<Bar>, then you can do

m_bar = bar->shared_from_this();
Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
8

The purpose of a weak pointer is to be unable to use the raw pointer if it had been deleted. However, if you have a raw pointer, the weak pointer has no way to know that it was deleted. Instead, you must have a shared_ptr somewhere which "owns" the raw pointer. Then you can create a weak_ptr which references the shared_ptr.

When the shared_ptr goes out of scope and is the last "strong" smart pointer, it will automatically delete the raw pointer. Then, when you try to lock the weak_ptr, it will see that there is no "strong" pointer remaining and therefore the object does not exist.

Keith4G
  • 387
  • 2
  • 11
3

Everything you've said seems perfectly reasonable, except for one thing:

void setBar(const Bar *bar)

This shouldn't take a raw pointer. It should take a weak_ptr ideally, or possibly a shared_ptr if you have some compelling argument.

The actual owner of the object in question should construct the weak_ptr and than call setBar with that. This preserves the ownership semantics. It looks like what you're doing is having the owning object take a raw pointer and pass that to setBar. This creates a semantic gap in the ownership of the object.

John Dibling
  • 99,718
  • 31
  • 186
  • 324
1

Pass shared pointer instead of raw pointer, and create your weak pointer from that shared pointer. This is really the only way if owner of the pointer is outside of a class.

Ilya Kobelevskiy
  • 5,245
  • 4
  • 24
  • 41