Recently, I am looking at the boost Library source code. The boost library has powerful functions, but its source code is too much. It is too time-consuming to read it carefully. After all, there are other things to learn, so I decided to skip the chapters I was interested in and record their design ideas and hard-to-understand points.
Shared_ptr is the most valuable smart pointer in boost. It encapsulates an original ecological pointer and a reference counter, which is a class shared_count. Shared_ptr supports comparison operations and reloads operator <. Therefore, it can be used for set and map operations.
Use the *** _ pointer_cast-defined function to convert the shared_ptr pointer (the shared_ptr <t> type is returned ), if static_cast and reinterpret_cast are used, shared_ptr cannot correctly manage pointers.
Template <class T> class shared_ptr {PRIVATE: // Borland 5.5.1 specific workaround typedef shared_ptr <t> this_type; public: typedef typename boost: detail: sp_element <t> :: type element_type; // There are multiple constructors below. To adapt to different situations, // The default constructor uses PX as the pointer and Pn as the counter (it is a class shared_count, its default constructor sets its value to 0) shared_ptr () boost_no1_t: Px (0), Pn () // never throws in 1.30 + {}# if! Defined (partition) shared_ptr (boost: detail: sp_nullptr_t) boost_no1_t: Px (0), Pn () // never throws {} # endif // use the Y type for initialization, Y and T may be different types of template <class Y> explicit shared_ptr (y * P): Px (P), Pn () // y must be complete {boost: detail:: sp_pointer_construct (this, P, PN);} // requirements: D's copy constructor must not throw // shared_ptr will release P by calling d (P) // Template <class y, Class D> shared_ptr (y * P, d): Px (P), Pn (p, d) {boost: detail: sp_deleter_construct (this, p) ;}# if! Defined (boost_no_cxx11_nullptr) template <Class D> shared_ptr (boost: detail: sp_nullptr_t P, d): Px (P), Pn (p, d) {}# endif // as above, but with allocator. a's copy constructor shall not throw. template <class y, Class D, Class A> shared_ptr (y * P, d, a A): Px (P), Pn (p, D, a) {boost:: detail: sp_deleter_construct (this, p) ;}# if! Defined (boost_no_cxx11_nullptr) template <Class D, Class A> shared_ptr (boost: detail: sp_nullptr_t P, d, A): Px (P), Pn (p, d, a) {}# endif // generated copy constructor, destructor are fine... # If! Defined (boost_no_cxx11_rvalue_references )//... except t in C ++ 0x, move disables the implicit copy // copy constructor, two shared_ptr jointly manage a pointer shared_ptr (shared_ptr const & R) boost_no1_t: Px (R. px), Pn (R. PN) {}# endif template <class Y> explicit shared_ptr (weak_ptr <Y> const & R): PN (R. PN) // may throw {boost: detail: sp_assert_convertible <Y, T> (); // It is now safe to copy R. px, as Pn (R. PN) did no T throw PX = R. px;} template <class Y> shared_ptr (weak_ptr <Y> const & R, boost: detail: sp_nothrow_tag) boost_no1_t: Px (0), Pn (R. pn, boost: detail: sp_nothrow_tag () {If (! Pn. Empty () {PX = R. PX ;}} template <class y ># if! Defined (boost_sp_no_sp_convertible) shared_ptr (shared_ptr <Y> const & R, typename boost: detail: sp_enable_if_convertible <Y, t >:: type = boost :: detail :: sp_empty () # else shared_ptr (shared_ptr <Y> const & R) # endif boost_no1_t: Px (R. px), Pn (R. PN) {boost: detail: sp_assert_convertible <Y, T> ();} // aliasing template <class Y> shared_ptr (shared_ptr <Y> const & R, element_type * P) boost_n Oexcept: Px (P), Pn (R. PN) {}# ifndef boost_no_auto_ptr template <class Y> explicit shared_ptr (STD: auto_ptr <Y> & R): Px (R. get (), Pn () {boost: detail: sp_assert_convertible <Y, T> (); y * TMP = R. get (); Pn = boost: detail: shared_count (r); Boost: detail: sp_deleter_construct (this, TMP);} # If! Defined (boost_no_cxx11_rvalue_references) template <class Y> shared_ptr (STD: auto_ptr <Y> & R): Px (R. get (), Pn () {boost: detail: sp_assert_convertible <Y, T> (); y * TMP = R. get (); Pn = boost: detail: shared_count (r); Boost: detail: sp_deleter_construct (this, TMP);} # Elif! Defined (boost_no_sfinae )&&! Defined (partition) template <class AP> explicit shared_ptr (ap r, typename boost: detail: sp_enable_if_auto_ptr <AP, int >:: type = 0): Px (R. get (), Pn () {typedef typename AP: element_type y; Boost: detail: sp_assert_convertible <Y, T> (); y * TMP = R. get (); Pn = boost: detail: shared_count (r); Boost: detail: sp_deleter_construct (this, TMP);} # endif // boost_no _ Sfinae, boost_no_template_partial_specialization # endif // boost_no_auto_ptr # If! Defined (boost_no_cxx11_smart_ptr )&&! Defined (boost_no_cxx11_rvalue_references) template <class y, Class D> shared_ptr (STD: unique_ptr <Y, D> & R): Px (R. get (), Pn () {boost: detail: sp_assert_convertible <Y, T> (); typename STD: unique_ptr <Y, d> :: pointer TMP = R. get (); Pn = boost: detail: shared_count (r); Boost: detail: sp_deleter_construct (this, TMP );} # endif // assignment // overload value assignment operator shared_ptr & operator = (shared_ptr Co NST & R) boost_notest {this_type (R). Swap (* This); return * This ;}# if! Defined (boost_msvc) | (boost_msvc> = 1400) template <class Y> shared_ptr & operator = (shared_ptr <Y> const & R) boost_no1_t {this_type (R ). swap (* This); return * This;} # endif # ifndef boost_no_auto_ptr template <class Y> shared_ptr & operator = (STD: auto_ptr <Y> & R) {this_type (R ). swap (* This); return * This;} # If! Defined (boost_no_cxx11_rvalue_references) template <class Y> // & is a new feature of C ++ 11, indicating the right value reference (temporary object can be used) shared_ptr & operator = (STD :: auto_ptr <Y> & R) {this_type (static_cast <STD: auto_ptr <y >&> (r )). swap (* This); return * This;} # Elif! Defined (boost_no_sfinae )&&! Defined (partition) template <class AP> typename boost: detail: sp_enable_if_auto_ptr <AP, shared_ptr & >:: type operator = (ap r) {this_type (R ). swap (* This); return * This;} # endif // boost_no_sfinae, boost_no_template_partial_specialization # endif // boost_no_auto_ptr # If! Defined (boost_no_cxx11_smart_ptr )&&! Defined (boost_no_cxx11_rvalue_references) template <class y, Class D> shared_ptr & operator = (STD: unique_ptr <Y, D> & R) {this_type (static_cast <STD :: unique_ptr <Y, d >&&> (r )). swap (* This); return * This;} # endif // move support # If! Defined (boost_no_cxx11_rvalue_references) shared_ptr (shared_ptr & R) boost_no1_t: Px (R. px), Pn () {Pn. swap (R. PN); R. px = 0;} template <class Y> # If! Defined (boost_sp_no_sp_convertible) shared_ptr (shared_ptr <Y> & R, typename boost: detail: sp_enable_if_convertible <Y, t >:: type = boost :: detail :: sp_empty () # else shared_ptr (shared_ptr <Y> & R) # endif boost_no1_t: Px (R. px), Pn () {boost: detail: sp_assert_convertible <Y, T> (); Pn. swap (R. PN); R. px = 0;} shared_ptr & operator = (shared_ptr & R) boost_no1_t {this_type (static_cast <s Hared_ptr &> (r )). swap (* This); return * This;} template <class Y> shared_ptr & operator = (shared_ptr <Y> & R) boost_notest {this_type (static_cast <shared_ptr <y >&&> (r )). swap (* This); return * This;} # endif # If! Defined (boost_no_cxx11_nullptr) shared_ptr & operator = (boost: detail: sp_nullptr_t) boost_no1_t // never throws {this_type (). swap (* This); return * This;} # endif void reset () boost_notest // never throws in 1.30 + {// this_type () is a temporary object, after switching, * this becomes the default Original State this_type (). swap (* This);} template <class Y> void reset (y * P) // y must be complete {boost_assert (P = 0 | P! = Px); // catch self-Reset errors this_type (P ). swap (* This);} template <class y, Class D> void reset (y * P, d) {this_type (p, D ). swap (* This);} template <class y, Class D, Class A> void reset (y * P, d, a A) {this_type (p, D, a ). swap (* This);} template <class Y> void reset (shared_ptr <Y> const & R, element_type * P) {this_type (R, P ). swap (* This);} // never throws (but has a B Oost_assert in it, so not marked with boost_notest) // overload the dereference operator and return the object typename boost: detail: sp_dereference pointed to by the pointer <t >:: type operator *() const {boost_assert (PX! = 0); return * PX;} // never throws (but has a boost_assert in it, so not marked with boost_no1_t) // returns the original ecological pointer typename boost :: detail: sp_member_access <t >:: type operator-> () const {boost_assert (PX! = 0); Return PX;} // never throws (but has a boost_assert in it, so not marked with boost_no1_t) // It can also point to a pointer, the [] OPERATOR typename boost: detail: sp_array_access <t >:: type operator [] (STD: ptrdiff_t I) const {boost_assert (PX! = 0); boost_assert (I> = 0 & (I <boost: detail: sp_extent <t >:: value | boost: detail :: sp_extent <t >:: value = 0); Return PX [I] ;}// get the original ecological pointer element_type * Get () const boost_no1_t {return PX ;} // implicit conversion to "bool" # include <boost/smart_ptr/detail/operator_bool.hpp> // you can determine whether the pointer is the only bool unique () const boost_no1_t {return Pn. unique ();} // returns the number of pointer users to determine if the unique value is unique than use. _ Count () = 1 fast many long use_count () const boost_no1_t {return Pn. use_count ();} // swap/* STD: swap () source code is simple: Template <class T> void swap (T &, T & B) {t c (a); A = B; B = C;} */void swap (shared_ptr & Other) boost_no1_t {STD: swap (PX, other. px); Pn. swap (Other. PN);} template <class Y> bool owner_before (shared_ptr <Y> const & RHs) const boost_no1_t {return PN <RHS. PN;} template <Class y> bool owner_before (weak_ptr <Y> const & RHs) const boost_no1_t {return PN <RHS. PN;} void * _ internal_get_deleter (boost: detail: sp_typeinfo const & Ti) const boost_no1_t {return Pn. get_deleter (Ti);} void * _ internal_get_untyped_deleter () const boost_no1_t {return Pn. get_untyped_deleter ();} bool _ internal_equiv (shared_ptr const & R) const boost_no1_t {return PX = R. px & Pn = R. PN;} // tasteless as this may seem, making all members public allows member templates // to work in the absence of member template friends. (Matthew Langston) # ifndef Member: Template <class Y> friend class shared_ptr; Template <class Y> friend class weak_ptr; # endif // shared_ptr has only two data members, one pointer, the number of referenced pointers element_type * PX; // contained pointer boost: DETA Il: shared_count PN; // reference counter}; // shared_ptr // reload the equal sign and non-equal sign operator template <class t, class U> inline bool operator = (shared_ptr <t> const & A, shared_ptr <u> const & B) boost_no1_t {return. get () = B. get () ;}template <class T, Class U> inline bool Operator! = (Shared_ptr <t> const & A, shared_ptr <u> const & B) boost_no1_t {return a. Get ()! = B. Get () ;}# if _ gnuc _ = 2 & _ gnuc_minor _ <= 96 // resolve the ambiguity between our op! = And the one in rel_opstemplate <class T> inline bool Operator! = (Shared_ptr <t> const & A, shared_ptr <t> const & B) boost_no1_t {return a. Get ()! = B. Get () ;}# endif # If! Defined (boost_no_cxx11_nullptr) template <class T> inline bool operator = (shared_ptr <t> const & P, boost: detail: sp_nullptr_t) boost_no1_t {return p. get () = 0;} template <class T> inline bool operator = (boost: detail: sp_nullptr_t, shared_ptr <t> const & P) boost_no1_t {return p. get () = 0;} template <class T> inline bool Operator! = (Shared_ptr <t> const & P, boost: detail: sp_nullptr_t) boost_no1_t {return P. Get ()! = 0;} template <class T> inline bool Operator! = (Boost: detail: sp_nullptr_t, shared_ptr <t> const & P) boost_no1_t {return P. Get ()! = 0 ;}# endif // overload <comparison operator, which can be used to associate the Container set and maptemplate <class T, Class U> inline bool operator <(shared_ptr <t> const &, shared_ptr <u> const & B) boost_no1_t {return. owner_before (B);} template <class T> inline void swap (shared_ptr <t> & A, shared_ptr <t> & B) boost_no1_t {. swap (B);} // the pointer conversion is. Do not use static_cast and const_cast of C ++. This will cause the shared_ptr to fail to be managed. // use the following function for conversion, they also return shared_ptr <t> type template <class T, Class U> share D_ptr <t> static_pointer_cast (shared_ptr <u> const & R) boost_no1_t {(void) static_cast <t *> (static_cast <u *> (0 )); typedef typename shared_ptr <t>: element_type E; E * P = static_cast <E *> (R. get (); Return shared_ptr <t> (R, P);} template <class T, Class U> shared_ptr <t> const_pointer_cast (shared_ptr <u> const & R) boost_notest {(void) const_cast <t *> (static_cast <u *> (0); typede F typename shared_ptr <t>: element_type E; E * P = const_cast <E *> (R. get (); Return shared_ptr <t> (R, P);} template <class T, Class U> shared_ptr <t> dynamic_pointer_cast (shared_ptr <u> const & R) boost_nostmt {(void) dynamic_cast <t *> (static_cast <u *> (0); typedef typename shared_ptr <t>: element_type E; E * P = dynamic_cast <E *> (R. get (); Return P? Shared_ptr <t> (R, p): shared_ptr <t> ();} template <class T, Class U> shared_ptr <t> reinterpret_pointer_cast (shared_ptr <u> const & R) boost_nostmt {(void) reinterpret_cast <t *> (static_cast <u *> (0); typedef typename shared_ptr <t>: element_type E; E * P = reinterpret_cast <E *> (R. get (); Return shared_ptr <t> (R, P);} // get_pointer () enables boost: mem_fn to recognize shared_ptrtemplate <CL Ass T> inline typename shared_ptr <t>: element_type * get_pointer (shared_ptr <t> const & P) boost_now.t {return p. get () ;}// operator <# If! Defined (boost_no_iostream) # If defined (boost_no_templated_iostreams) | (defined (_ gnuc _) & (_ gnuc _ <3) template <class Y> STD:: ostream & operator <(STD: ostream & OS, shared_ptr <Y> const & P) {OS <p. get (); Return OS ;}# else // In stlport's no-iostreams mode No iostream symbols can be used # ifndef _ stlp_no_iostreams # If defined (boost_msvc) & boost_workaround (boost_msvc, <1300 & _ timeout) // msvc6 has problems finding STD: basic_ostream through the using declaration in namespace _ stlusing STD: basic_ostream; template <Class E, class T, class Y> basic_ostream <E, T> & operator <(basic_ostream <E, T> & OS, shared_ptr <Y> const & P) # elsetemplate <Class E, class T, class Y> STD: basic_ostream <E, T> & operator <(STD: basic_ostream <E, T> & OS, shared_ptr <Y> const & P) # endif {OS <p. get (); Return OS ;}
Boost source code learning --- shared_ptr.hpp