[Original] shared_ptr of C ++ 11 smart pointer

Source: Internet
Author: User
Shared_ptr is a reference counting smart pointer used to share the ownership of objects. It can be constructed from a bare pointer, shared_ptr, auto_ptr, or weak_ptr. You can also pass the second parameter to the shared_ptr constructor, which is called the er ). The deleteer is used to process the release of shared resources, which is useful for managing resources that are not allocated with new or deleted. After shared_ptr is created, it can be used like a normal pointer. It cannot be explicitly deleted except for one point. Shared_ptr has the following important interfaces: Template <class T> Explicit shared_ptr (T * P ); This constructor obtains the ownership of the given pointer p. The parameter P must be a valid pointer to T. After the construction, the reference count is set to 1. The only exception thrown from this constructor is STD: bad_alloc (only in rare cases, that is, the space required to reference the counter cannot be obtained ).   Template <class T, Class D> Shared_ptr (T * P, d ); This constructor has two parameters. The first is the resource that shared_ptr will obtain ownership of, and the second is an object that is responsible for releasing resources when shared_ptr is destroyed. The saved resource will be d (P) to the object. If the reference counter cannot be allocated successfully, shared_ptr throws an exception of the STD: bad_alloc type.   Shared_ptr (const shared_ptr & R ); The resources saved in R are shared by the newly constructed shared_ptr, and the reference count is incremented by one. This constructor will not throw an exception.   Template <class T> Explicit shared_ptr (const weak_ptr <t> & R ); Construct shared_ptr from a weak_ptr. This makes the use of weak_ptr thread-safe, because the reference count of the shared resources pointing to the weak_ptr parameter will automatically increase (weak_ptr does not affect the reference count of shared resources ). If weak_ptr is empty (R. use_count () = 0), shared_ptr throws an exception of the bad_weak_ptr type.   Template <typename T> Shared_ptr (auto_ptr <t> & R ); This constructor obtains the ownership of the pointer stored in R from an auto_ptr by saving a copy of the pointer and calling release for auto_ptr. After the construction, the reference count is 1, and R is null. If the reference counter cannot be allocated successfully, STD: bad_alloc is thrown.   ~ Shared_ptr (); Shared_ptr destructor, which reduces the reference count by one. If the count is zero, the saved pointer is deleted. The method for deleting a pointer is to call operator delete, or, if a delete object is specified to execute the delete operation, the saved pointer is used as a unique parameter to call this object. The Destructor does not throw an exception.   Shared_ptr & operator = (const shared_ptr & R ); Assign a value to share resources in R and stop sharing original resources. The value assignment operation does not throw an exception.   Void reset (); The reset function is used to stop sharing ownership of the stored pointer. The reference count of the shared resource is reduced by one.   T & operator * () const; This operator returns a reference to the object pointed to by the existing pointer. If the pointer is null, Calling operator * will lead to undefined behavior. This operator does not throw an exception.   T * operator-> () const; This operator returns the saved pointer. Together with operator *, this operator makes smart pointers look like normal pointers. This operator does not throw an exception.   T * Get () const; The get function is the best way to obtain the stored pointer when it may be null (in this case, operator * and operator-> will lead to undefined behavior. Note: You can also use implicit boolean type conversion to test whether shared_ptr contains valid pointers. This function does not throw an exception.   Bool unique () const; This function returns true if shared_ptr is the unique owner of the pointer it stores; otherwise, false. Unique does not throw an exception.   Long use_count () const; The use_count function returns the reference count of the pointer. It is particularly useful during debugging because it can be used inProgramObtain the reference count snapshot from the execution key. Use it with caution, because in some possible shared_ptr implementations, the calculation reference count may be expensive or even unavailable. This function does not throw an exception.   Operator unspecified-bool-type () const; This is an implicit conversion function of the unspecified-bool-type. It can test a smart pointer in the Boolean context. If shared_ptr stores a valid pointer, the returned value is true; otherwise, the value is false. Note that the type returned by the conversion function is uncertain. Using the return type as bool will lead to some absurd operations. Therefore, the typical implementation adopts safe bool idiom, which ensures that only applicable Boolean tests can be used. This function does not throw an exception.   Void swap (shared_ptr <t> & B ); This facilitates the exchange of two shared_ptr. Swap functions exchange stored pointers (and their reference counts ). This function does not throw an exception.   Template <typename T, typename u> shared_ptr <t> static_pointer_cast (const shared_ptr <u> & R ); To execute static_cast on the pointer stored in shared_ptr, we can take out the pointer and forcibly convert it, but we cannot store it in another shared_ptr; the new shared_ptr considers it the first to manage these resources. The solution is to use static_pointer_cast, which ensures that the reference count of the object to be referenced is correct. Static_pointer_cast does not throw an exception. Example of using shared_ptrCodeAs follows:
 1   {  2 Shared_ptr < Int > Pint1;  3 Assert (pint1.use _ count () = 0 ); //  Pointer not referenced  4   {  5 Shared_ptr < Int > Pint2 ( New   Int ( 5  ));  6 Assert (pint2.use _ count () = 1 ); // New int (5) This pointer is referenced once  7   8 Pint1 = Pint2;  9 Assert (pint2.use _ count () = 2 ); //  New int (5) This pointer is referenced twice  10 Assert (pint1.use _ count () = 2  );  11 } // Pint2 leaves the scope, so the number of times new int (5) is referenced-1  12   13 Assert (pint1.use _ count () = 1  );  14 } //  Pint1 leaves the scope, the number of times of reference-1, now new int (5) is referenced 0 times, so destroy it 

If the creation and destruction of resources are not performed in the form of new and delete, what should we do? You can see through the interface above that the shared_ptr constructor can specify the deleteer. The sample code is as follows:

 1   Class  Filecloser 2   {  3   Public  :  4       Void   Operator () (File * PF)  5   {  6            If (PF! = Null)  7   {  8  Fclose (PF );  9 PF = NULL;  10   }  11   }  12   };  13   14 Shared_ptr <File> FP (fopen (pszconfigfile, "  R  " ), Filecloser ());

When using shared_ptr, you must avoid the situation that the same object pointer is treated as a parameter in the shard_ptr constructor twice. Consider the following code:

 1   {  2        Int * Pint = New   Int ( 5  );  3 Shared_ptr <Int > Temp1 (pint );  4 Assert (temp1.use _ count () = 1  );  5 Shared_ptr < Int > Temp2 (pint );  6 Assert (temp2.use _ count () = 1  );  7 } //  Both temp1 and temp2 leave the scope, and both destroy pint, which will cause the same memory to be released twice. 
The correct method is to assign the original pointer to the smart pointer, and all subsequent operations will be targeted at the smart pointer. The reference code is as follows:

  1  {  2  shared_ptr  int  temp1 ( New   int  ( 5   ));   3  assert (temp1.use _ count () =  1   );   4  shared_ptr  int   temp2 (temp1);   5  assert (temp2.use _ count () =  2  );   6 }< span style = "color: #008000;" >///   both temp1 and temp2 are out of the scope, the number of references is 0, and the pointer is destroyed.  
In addition, when shared_ptr is used to wrap this, it will also generate a problem similar to the above class. Consider the following code:
 1   Class  A  2   {  3   Public  :  4 Shared_ptr <A> Get ()  5   {  6                Return Shared_ptr <A> (This  );  7   }  8   }  9   10 Shared_ptr <A> PA ( New  A ());  11 Shared_ptr <A> Pb = pa-> get ();

When pa and Pb leave the scope, the objects on the stack will be released twice. How can this problem be solved? C ++ 11 provides the following mechanism: class is derived from the enable_shared_from_this class, And shared_from_this interface is used when obtaining shared_ptr. The reference code is as follows:

  1   class :  Public  enable_shared_from_this   2  {  3   Public  :   4  shared_ptr   get ()   5  {  6   return   shared_from_this ();   7  }  8 }

If shared_ptr is used in multiple threads, the count may be invalid due to the simultaneous access to the reference count. The solution is to pass the public week_ptr to each thread. When shared_ptr is required in the thread, convert week_ptr to shared_ptr.

Related Article

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.