The role and implementation of the enable_shared_from_this class,

Source: Internet
Author: User

The role and implementation of the enable_shared_from_this class,
Example

In practice, you often need to obtain your own shared_ptr within an object managed by shared_ptr. For example:

  • Construct a shared_ptr using the this pointer, as shown below:
1 struct Bad 2 {3 void fun () 4 {5 shared_ptr <Bad> sp {this}; 6 cout <sp-> count () <endl; 7} 8}; 9 shared_ptr <Bad> sp {make_shared <Bad> ()}; 10 sp-> fun (); // The output is 1

However, note that the shared_ptr constructed in this way does not share a counter with other shared_ptr. In this case, the object will be released repeatedly during the analysis, leading to an error.

The correct method is to inherit the enable_shared_from_this class and call the sahred_from_this () function to generate shared_ptr. The usage is as follows:

1 struct Good: public std: enable_shared_from_this <Good> 2 {3 void fun () 4 {5 shared_ptr <Good> sp {shared_from_this ()}; 6 cout <sp-> count () <endl; 7} 8}; 9 shared_ptr <Good> sp {make_shared <Good> ()}; // -------------- * 1*10 sp-> fun (); // The output is 2.

In the class, use the shared_from_this () function defined by enable_shared_from_this to construct a shared_ptr <Good> object, which can share a Good object with other shared_ptr objects.

Enable_shared_from_this Implementation Analysis (gcc-7.2.0-based source code)

Most implementations are implemented through weak_ptr. first, use the pointer of the object to be managed (obj) and the existing shared_ptr (sp1 ,..., the number of SPNs (spi-> use_count () to initialize a weak_ptr <Obj> (& obj, spi-> use_count (), and then construct a shared_ptr using this weak_ptr.

1 // enable_shared_from_this implementation 2 // based on (/usr/include/c ++/7.3.0/bits/shared_ptr.h) 3 // This code is a simplified version of gcc implementation, it is used only to describe the principle. 4 template <typename T> 5 class enable_shared_from_this 6 {7 public: 8 shared_ptr <T> shared_from_this () 9 {10 return shared_ptr <T> (this-> weak_this ); 11} 12 shared_ptr <const T> shared_from_this () const13 {14 return shared_ptr <const T> (this-> weak_this); 15} 16 private: 17 template <typename> 18 friend class shared_ptr; 19 20 template <typename T1> 21 void _ M_weak_assign (T1 * p, const shared_count <> & n) 22 {23 weak_this. _ M_assign (p, n); 24} 25 26 mutable weak_ptr <T> weak_this; 27 };

The enable_shared_from_this <T> class defines a weak_ptr <T>, which serves to generate a shared_ptr <T> object from the obj pointer. according to the previous principle, we may think that we initialize weak_this at the same time during obj initialization, but it is clear that weak_this is not initialized in this Code (not in the original code. Why doesn't gcc implement it like this ?).

Gcc processes weak_ptr in the shared_ptr constructor <T>. from the perspective of the Good class, weak_ptr <Good> weak_this in the Good object is processed at * 1 *, so that it points to a valid Good object and modifies use_count. the usage of the above Good class for enable_shared_from_this is a few valid methods, which must be guaranteed. If shared_from_this () is called for an object, this object must be held by shared_ptr <T>. from the above principle, we can understand the reason for this: the first shared_ptr holding the Good object g_obj <T> sp1 will process weak_this of g_obj to make it valid. without this step, when shared_from_this () is called, weak_this is an invalid value, that is, weak_this.expire () = true, an exception is thrown.

So how do we deal with weak_ptr in the shared_ptr constructor?

Shared_ptr defines such a function (from class _ shared_ptr in/usr/include/c ++/7.3.0/bits/shared_ptr_base.h ):

 1 template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type> 2 typename enable_if<__has_esft_base<_Yp2>::value>::type 3 _M_enable_shared_from_this_with(_Yp* __p) noexcept 4 { 5     if(auto __base = __enable_shared_from_this_base(_M_refcount, __p)) 6         __base->_M_weak_assign(const_cast<_Yp2*>(__p), _M_refcount); 7 } 8  9 template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type>10 typename enable_if<!__has_esft_base<_Yp2>::value>::type11 _M_enable_shared_from_this_with(_Yp*) noexcept { }

_ Yp is the type of objects managed by shared_ptr. The two template functions are represented as follows:

When _ Yp is a subclass of make_shared_from_this, the first function is generated. Its function is to call the _ M_weak_assign function through the pointer of the _ Yp object to modify the weak_this Member of the _ Yp object, in fact, _ M_weak_assign calls the _ M_assign function.

Otherwise, the second function is generated, which does not work.

 1 // from shared_ptr_base.h class __weak_ptr, derived by weak_ptr 2  3 void _M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount) noexcept 4 { 5     if (use_count() == 0) 6     { 7         _M_ptr = __ptr; 8         _M_refcount = __refcount; 9     }10 }

The _ M_enable_shared_from_this_with function is called in the shared_ptr <_ Yp> constructor to check whether _ Yp inherits from make_shared_from_this and perform corresponding processing. here, _ M_refcount is a member of shared_ptr, which is used to record the number of shared_ptr management operations on _ Yp. in this way, the weak_ptr processing is completed to make it a valid value. when you call the shared_from_this () function later, you can use weak_this to call the shared_ptr constructor to generate a shared_ptr that shares the same object.

The above code references the instance code on cppreference and the source code of gcc.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.