C++11 enable_shared_from_this uses

The C++11 enable_shared_from_this is a class template which has the 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‘.

Link :C++ shared_ptr

For a class to be able to access the 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. We can say the enable_shared_from_this class -through the 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 its own such function). This
function is called by the shared_ptr constructor if the class inherit from the enable_shared_from_this class. This function belongs to the 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 class

A class inheriting enable_shared_from_this are allowed to call the function shared_from_this(). And this function allows a safe way to share the objects between different shared_ptr, which 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 wants 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 it is 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 has not increased. 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 will 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 its own such function with a different name, other compilers will also have its own version.




Leave a Reply

Your email address will not be published. Required fields are marked *