Question

I am moving to using C++11 shared pointers.

I need to write member functions that adds pointers to the instance of their class to containers ( i.e. registers ( adds ) their presence in some collection )

Using plain old pointers, I can do this

class myClass {
public:
    void Register( std::vector< myClass* >& v_registrants )
    {
        v_registrants.push_back( this );
    }
};

But how to do the same when the collection holds shared pointers? Somehow the member function must obtain a copy of the shared pointer that owns the instance.

I cannot simply create a new shared pointer from this because:

If two shared_ptr are constructed (or made) from the same (non-shared_ptr) pointer, they will both be owning the pointer without sharing it, causing potential access problems when one of them releases it (deleting its managed object) and leaving the other pointing to an invalid location. ( reference )

So, what to do to implement the following class?

class myClass_safe {
public:
    void Register( std::vector< std::shared_ptr<myClass_safe > >& v_registrants )
    {
        //v_registrants.push_back( this );  // compiler freaks out
    }
};

As a workaround, I am doing this:

class myClass_safe {
public:
    void Register( 
        std::shared_ptr<myClass_safe >& my_shared_ptr,
        std::vector< std::shared_ptr<myClass_safe > >& v_registrants )
    {
        v_registrants.push_back( my_shared_ptr );  
    }
};

Which results in this rather strange code

// register the object
object->Register( object, v_registrants );

Is there not something better than this?

Was it helpful?

Solution

I believe this is exactly what std::enable_shared_from_this is intended for.

Inheriting from std::enable_shared_from_this<classname> provides your class with a member function called shared_from_this, that enables you to safely obtain a std::shared_ptr that shares ownership with the original owner.

So to use it, in your case, you would have to change your class definition like this:

class myClass_safe : public std::enable_shared_from_this<myClass_safe> {
public:
    void Register( std::vector< std::shared_ptr<myClass_safe > >& v_registrants )
    {
        v_registrants.push_back( shared_from_this() );
    }
};

Note also, that the object must be owned by a shared pointer prior to calling shared_from_this.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top