Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

shared_ptr and the this-pointer

OK, I started using shared-pointers and pass shared-pointers as much as possible. No conversion to raw pointers anymore. This works good, except in this specific case:

Suppose we have a class that also is an observer on another class, like this:

class MyClass : public IObserver
   {
   public:
      MyClass (std::shared_ptr<SomeOtherClass> otherClass);
      void DoSomethingImportant();
   private:
      std::shared_ptr<SomeOtherClass> m_otherClass;
   };

This class is used like this in my application:

std::shared_ptr<MyClass> myInstance(new MyClass(otherInstance));
...
myInstance->DoSomethingImportant();

MyClass gets a shared-pointer to another class and stores this in its m_otherClass data member. In the DoSomethingImportant method, the MyClass instance does lots of important things, including registering itself as an observer on m_otherClass, like this:

m_otherClass->registerObserver(this);

The problem is that the registerObserver method is defined like this:

void registerObserver (std::shared_ptr observer);

It expects a shared pointer, but 'this' is a raw pointer, not a shared one.

I see three ways of solving this:

  • Find a trick to convert a normal pointer to a shared pointer (see question convert pointer to shared_ptr), but the answers to that question only suggest to copy the shared-pointers, not on how to actually convert the pointer to a shared pointer.
  • Pass the shared-pointer to ourself to the method, like this: "myInstance->DoSomethingImportant(myInstance);" which seems a bit stupid.
  • Put the observer part into a separate class. This looks like some overkill, and might make the class harder to understand.

This problem makes it obvious that shared-pointers are just an add-on to C++ (I don't think you have the same problem in other languages/environments like C# (or .Net in general) and Java).

Any other suggestions or tricks on how to handle this situation?

like image 347
Patrick Avatar asked Feb 02 '11 08:02

Patrick


People also ask

Is shared_ptr a pointer?

The shared_ptr type is a smart pointer in the C++ standard library that is designed for scenarios in which more than one owner might have to manage the lifetime of the object in memory.

Do I need to delete a shared_ptr?

The purpose of shared_ptr is to manage an object that no one "person" has the right or responsibility to delete, because there could be others sharing ownership. So you shouldn't ever want to, either.

What happens when you move shared_ptr?

By moving the shared_ptr instead of copying it, we "steal" the atomic reference count and we nullify the other shared_ptr . "stealing" the reference count is not atomic, and it is hundred times faster than copying the shared_ptr (and causing atomic reference increment or decrement).

When should you use a shared_ptr?

An object referenced by the contained raw pointer will not be destroyed until reference count is greater than zero i.e. until all copies of shared_ptr have been deleted. So, we should use shared_ptr when we want to assign one raw pointer to multiple owners. // referring to the same managed object.


1 Answers

What you need is probably the enable_shared_from_this and shared_from_this facilities. The docs are here

Note that you cannot use shared_from_this until the constructor has fully completed and the object is already owned by another shared_ptr.

struct test : boost::enabled_shared_from_this<test>
{
    test() {
       // shared_from_this(this); // error, still not owned by another shared_ptr
    }
    boost::shared_ptr<test> shared() {
       return shared_from_this(this);
    }
};
int main() {
   test * t = new test;
   // boost::shared_ptr<test> p = t->shared(); // error, not yet owned by other shared_ptr
   boost::shared_ptr<test> owner( t ); 
   boost::shared_ptr<test> p = t->shared();     // [*] ok, "owner" owns the object
}

[*] This part of the example is silly, you could just copy owner into p, instead of calling the method. It is just presented to note when it is ok or not to called shared_from_this inside the test methods.

like image 178
David Rodríguez - dribeas Avatar answered Sep 30 '22 11:09

David Rodríguez - dribeas