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.