C++11 enable_shared_from_this :: uses


C++11 enable_shared_from_this template

The C++11 enable_shared_from_this is a class template which has a member function shared_from_this().The purpose of this member function is to return a shared_ptr that points to the current object i.e. the shared_ptr that points to ‘this‘.For a class to be able to access this function it must inherit the class enable_shared_from_this publicly.Consider the code below.

class A:public enable_shared_from_this<A>
{
public:
A() { }

~A() { }
};

int main( )
{
shared_ptr<A>sp(new A()) ,
  sp1 ;

sp1=sp->shared_from_this() ;

cout<< sp1.use_count() ;

cin.get() ;
return 0 ;
}

If we look at the line sp1=sp->shared_from_this() ,it could have been written as sp1=sp;directly assigning a shared_ptr to another shared_ptr.The purpose of using shared_from_this() function is to assign a shared_ptr object to another object with the increase in reference count.Of course direct assignment would have also increased the reference count.So we can say enable_shared_from_this class-through shared_from_this() function- provides an alternative means to assign one shared_pr to another shared_ptr safely.More specific use of shared_from_this() is discuss in the coming section.

Note you must inherit this class publicly else you will get certain errors depending on your IDE.If you use Code::blocks the compiler will complain “enable_shared_from_this is an inaccessible base of “.To understand why the compiler throw this error message you need to know that there is a function known as __enable_shared_from_this_helper()(this function is meant only for CB,VS has it’s own such function) function which the shared_ptr constructor will call if the class inherit from the enable_shared_from_this class.This function belongs to enable_shared_from_this class and it is defined as a private function.So if enable_shared_from_this is inherited privately by the class,calling this function is not possible,and so the compiler throws the error message.In Visual Studio bad_weak_ptr exception is thrown if the class is inherited privately.





Uses of enable_shared_from_this

A class inheriting from enable_shared_from_this and calling the function shared_from_this() allows a safe way to share the objects between different shared_ptr and it does so by increasing the reference count.This is indeed the main purpose of making a class inherit from enable_shared_from_this class.But how does the derive class actually benefit from using this class? the explanation is given below.

Suppose you have a class and one of the member functions want to return a shared_ptr pointing to ‘this’.How would you define such function? One way of doing it is shown below.

class Share
{
public:
Share() { }

shared_ptr<Share> get_shared_ptr( )
{ return shared_ptr<Share>(this); }

~Share() { }
};

This way of defining the function get_shared_ptr() has a drawback and a big one.To show you how it has a drawback we will declare a shared_ptr and we will call the function get_shared_ptr() to initialize another shared_ptr of the type Share class.

class Share
{
public:
Share() { }

shared_ptr<Share> get_shared_ptr( )
{ return shared_ptr<Share>(this); }

~Share() { }
};

int main( )
{
shared_ptr<Share> sp(new Share()) ;

shared_ptr<Share> spS=sp->get_shared_ptr() ;

cout<< spS.use_count() ;

return 0;
}

Run the program,you will notice that the reference count of sp is 1,it should be 2 actually.Unfortunately the reference count does not increase.This ultimately leads to a disaster ;one shared_ptr will point to invalid storage if the other goes out of scope.To get rid of this situation easily we will do a little modification in our code.We make the class Share inherit from enable_shared_from_this class and inside the function get_shared_ptr() instead of returning ‘shared_ptr<Share>(this)‘ ,we return ‘shared_from_this()‘.The modification will look like this.

class Share :public enable_shared_from_this<Share>
{
public:
Share() { }

shared_ptr<Share> get_shared_ptr( )
{ return shared_from_this() ; }

~Share() { }
};

int main( )
{
shared_ptr<Share> sp(new Share()) ;

shared_ptr<Share> spS=sp->get_shared_ptr() ;

cout<< spS.use_count() ;

return 0;
}

Now the reference count output is 2,hurray! everything is safe now.Well you can see that inheriting from the class enable_shared_from_this and using the function shared_from_this() can do a very helpful magic trick.


Implementation of enable_shared_from_this class

The code below shows how the class enable_shared_from_this can be implemented or defined.

template<class T> class enable_shared_from_this
{
private:
 weak_ptr<T> _weak_this;

protected:
 constexpr enable_shared_from_this() : _weak_this() { }
 enable_shared_from_this(enable_shared_from_this const &) { }
 enable_shared_from_this& operator=(enable_shared_from_this const &) { return *this; }
 ~enable_shared_from_this( ) { }

public:
 shared_ptr<T> shared_from_this( ) { return shared_ptr<T>( _weak_this ); }
 shared_ptr<T const> shared_from_this( ) const { return shared_ptr<T const>( _weak_this ); }
};

The ‘_weak_this’ is a weak_ptr pointing to the current object.If you use the above class as it is it will not behave like the original enable_shared_from_this class because there is no function to initialize ‘_weak_this’ to the current object.So you need to include a function that will initialize ‘_weak_this’ to the object.In MinGw the function ‘__enable_shared_from_this_helper()’ does the job of initializing the ‘_weak_this’ pointer.Visual Studio has it’s own such function with a different name,other compiler will also have it’s own version.


Related Link

->C++11 Smart pointer : Shared pointer ; why is it call shared pointers?

->bad_weak_ptr :a class thrown as exception by shared_ptr.