9

I have a method on a class to make a particular instance an "active" instance:

void makeActive() { activeInstance = this; }

However it doesn't work since activeInstance has type std::shared_ptr< ClassName >. How can I cast this to std::shared_ptr<ClassName>?

Barry
  • 286,269
  • 29
  • 621
  • 977
Alexander
  • 1,299
  • 2
  • 12
  • 32
  • possible duplicate of [Create a boost::shared\_ptr to an existing variable](http://stackoverflow.com/questions/8466459/create-a-boostshared-ptr-to-an-existing-variable) – timrau Jan 12 '15 at 01:49
  • 2
    This uses `std::shared_ptr`, so some semantics might differ. – Mike DeSimone Jan 12 '15 at 01:52

2 Answers2

23

If your object is already owned by a shared_ptr, you can produce another shared_ptr by having your object inherit from std::enable_shared_from_this

This code will then work:

void makeActive() { activeInstance = shared_from_this(); }

If your object is not already owned by a shared_ptr, then you sure as heck don't want to create one in makeActive() since a shared_ptr will try to delete your object when the last one is destroyed.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
  • You can still create a shared_ptr if your object is not already maintained by one. See my answer. – John Zwinck Jan 12 '15 at 02:00
  • @JohnZwinck I totally agree... you can see that I was careful not to say that it *can't be done*. – Drew Dormann Jan 12 '15 at 02:02
  • 2
    You said "a shared_ptr will try to delete your object when the last one is destroyed" but this is not true if you use a null deleter as I explain in my answer. Saying "you sure as heck don't want to create one" is too strong a statement, because it is possible to do it safely. – John Zwinck Jan 12 '15 at 02:05
  • @JohnZwinck +1 to your answer. I can't be comfortable with adding the "null deleter" proposition as *safe code*, but please keep your answer up as well. – Drew Dormann Jan 15 '15 at 04:51
3

This will "work" (but see below):

activeInstance.reset(this);

The problem is, what does it mean? When activeInstance goes out of scope, this will be deleted. That may not be what you want. You should also read about enable_shared_from_this, which would allow you to say:

activeInstance = shared_from_this();

Another option is to use a "null deleter", that is, specify a deleter function which does nothing:

void NoDelete(void*) {}

activeInstance.reset(this, NoDelete);

In many cases this will be a safe and correct solution, assuming that this will be deleted by some other method elsewhere, and not before the last dereference of activeInstance.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • I'm pretty sure `activeInstance` is either a global or static class member, and thus won't go out of scope. – Mike DeSimone Jan 12 '15 at 01:53
  • 1
    @MikeDeSimone: well then it will be destroyed on program exit, which may still lead to a double-delete, therefore undefined behavior. – John Zwinck Jan 12 '15 at 01:55
  • 4
    Or use the aliasing constructor instead of a null deleter: `activeInstance = std::shared_ptr(std::shared_ptr(), this);` – T.C. Jan 12 '15 at 02:10
  • T.C.'s suggestion has the advantage that the shared_ptr won't allocate a control block internally. The disadvantage, though, is that you can't use weak_ptrs. – Peter Ruderman Jan 14 '15 at 20:01