Recently in the "C + + Primer Plus" Sixth Edition, this is indeed a good book, which the chapter on the smart pointer resolution is very clear, a solution to my previous many confusion. In the C + + interview process, many interviewers like to ask questions related to smart pointers, such as what smart pointers do you know? What is the design principle of shared_ptr? If you let yourself design a smart pointer, how do you do it? Wait a minute....... And when looking at Open source C + + projects, you can also see the shadow of the smart pointer everywhere. This shows that the smart pointer is not only the interviewer love to ask the subject matter, but also very practical value.
C + + uses a pair of operator new and delete for dynamic memory management, new allocates space for the object in dynamic memory and returns a pointer to the object, delete accepts a pointer to a dynamic object, destroys the object, and frees the associated memory. However, the use of such dynamic memory is dangerous because there is no guarantee that the memory object can always be freed at the right time. If you forget to free memory, it can cause memory leaks, and if you release the memory with a pointer to the memory, you will have a pointer to the illegal access memory.
In C++11, the new standard library provides two types of smart pointers (smart pointer) to manage objects more securely. The use of smart pointers is similar to regular pointers, except that they automatically release the functionality of the objects they point to. The difference between the two pointers is in how the underlying pointer is managed: SHARED_PTR allows multiple pointers to point to the same object, unique_ptr not supported. The standard library also provides a weak pointer to weak_ptr, pointing to Objects managed by shared_ptr. All three types are defined in the header file memory.
The use of shared_ptr is similar to the vector, which describes the type of object pointed to in the angle brackets:
Copy Code code as follows:
shared_ptr<string> P1//P1 is shared_ptr, pointing to String type
shared_ptr<list<int>> P2//P2 is shared_ptr, pointing to the int of the list
The solution references a smart pointer to the object it points to, and using a smart pointer in an if statement can determine whether the object it points to is empty:
Copy Code code as follows:
If P1 is not null, check to see if P1 points to an empty string object
if (P1 && p1->empty ())
*P1 = "creat"; If the P1 is non-null and points to an empty string object, the dereference P1 is assigned a new value creat
The safest way to allocate and use shared_ptr is to call the standard library function called make_shared. This function allocates and initializes it in dynamic memory, returning the shared_ptr that points to the object. The function is defined in memory.
Make_shared's definition is similar to shared_ptr, you must make the type of object you want to create, such as:
shared_ptr
shared_ptr<int> p3 = make_shared<int>) (1) pointing to an int with a value of 1;
shared_ptr
shared_ptr<string> P4 = make_shared<string> (3, "w") pointing to a string with a value of "www";
Point to an initialized int with a value of 0
shared_ptr<int> P5 = make_shared<int>) ();
You can also save make_shared using the Auto definition object, which eliminates the hassle of writing shared_ptr.
The shared--ptr has an associated indicator, called a reference count. Can be seen as a counter, whenever a shared_ptr object is copied, such as using a shared_ptr object to initialize another shared_ptr object, as an argument to a function, and as a function return value, the reference count is incremented (treated as a value + 1). When a new value is given to the shared_ptr or the shared_ptr is destroyed, the reference count is decremented. When the reference count is reduced to 0, through the destructor, shared_ptr automatically destroys the managed object and frees the memory.
It should be noted that if multiple objects share the underlying data, when an object is destroyed, the underlying data cannot be destroyed unilaterally, for example:
Blob<string> B1;
{//New scope
Blob<string> B2 = {"X", "B", "B"};
B1 = b2;
} When leaving the local scope, the B2 is destroyed, however the element xbb in B2 is not destroyed
//B1 points to elements originally created by B2, that is, "X", "B", "B", and B1 can still
WEAK_PTR is a smart pointer to an object that shared_ptr manages, but it does not control the lifetime of the object being pointed to. Binding a weak_ptr on the shared_ptr does not change the reference count of the shared_ptr, and once the last shared_ptr object is destroyed, the object is released, and there is no weak_ptr and no egg effect. My understanding is that WEAK_PTR provides the ability to point to shared_ptr's underlying data, controlling access to the underlying data by shared_ptr.
Because the object that weak_ptr points to may not exist (when the last object that shared_ptr points to is destroyed), and therefore cannot directly access the object, you must call the Lock function to check whether the object it points to exists. It is easy to write a selection statement to control:
Auto BB = make_shared<string> (2, ' B ');
weak_ptr<string> Xbb (BB);
if (shared_pr<int> NP = Xbb.lock ()) {//NP NOT NULL condition set up
//In if statement, NP and XBB shared objects
}
Complement weak_ptr related functions for easy understanding:
W.reset the W to Empty
Number of W.use_count () and W shared objects
W.expired () if W.use_count () is 0, returns True, otherwise returns false
W.lock () if w.expired () is true, returns an empty shared_ptr or returns an object that points to W shared_ptr
Add "C + + Primer 5th" in the 12.19 reference, and "smart pointers and exceptions" in this essay is not introduced
#include <iostream> #include <string> #include <vector> #include <memory> #include <initia
Lizer_list> using namespace std;
Using Std::string;
Using Std::vector;
Class Strblobptr; Class Strblob {Public:friend class strblobptr; Friend Strblobptr begin (); Declares the Begin () and end () Strblobptr end () in the Strblob class; Returns a strblobptr public:typedef Vector<string>::size_type size_type that points to itself; Type alias, Size_type = Vector<string>::size_type Strblob::strblob (initializer_list<string> il): Data (Make_ shared<vector<string>> (IL)) {}; The constructor that accepts a initializer_list parameter passes its arguments to the corresponding vector constructor by copying the list St Rblob::strblob (): Data (make_shared<vector<string>> ()) {}; constructor, initializes the data member, points to the value in the dynamically allocated vector, initializes the vector element void push_back (const string &t)
{data->push_back (t);} String& Strblob::front () {check (0, "front on Empty Strblob");
return Data->front ();
} string& Strblob::back () {check (0, "Back on Empty Strblob");
return Data->back ();
} void Strblob::p op_back () {//delete tail element check (0, "Pop_back empty Strblob");
return Data->pop_back ();
} string& Front () const {return Data->front ();};
string& back () const {return data->back ();};
Private:shared_ptr<vector<string>> data; void Strblob::check (Size_type i, const string &msg) const {//Check element exists if (I >= data->size ()) If there is no throw out_of_range (msg);
Throw exception}};
Class Strblobptr {public:strblobptr (): Curr (0) {};
Strblobptr (Strblob &a, size_t sz = 0): wptr (A.data), Curr (SZ) {};
String & Deref () const {Auto p = check (Curr, "dereference past End"); return (*P) [Curr]; Check succeeded, return a P pointer, point to make_shared vector}//dereference, make_sHared gets the vector and returns the object on Curr position strblobptr& incr () {check (Curr, increment past end of strblobptr) with the following table operator;
++curr;
return *this;
BOOL operator!= (const strblobptr& p) {return p.curr!= Curr;}
Private:weak_ptr<vector<string>> wptr;
size_t Curr;
shared_ptr<vector<string>> Check (size_t i, const string& msg) const {Auto rent = Wptr.lock ();
if (!rent) throw Runtime_error ("unbound strblobptr");
if (I >= rent->size ()) throw Out_of_range (msg);
return rent;
}
};
Strblobptr Strblob::begin () {return strblobptr (*this);}
Strblobptr Strblob::end () {return strblobptr (*this, Data->size ());}