This section studies the related problems of smart pointers;
Simple implementation of UNIQUE_PTR
Template <typename t> class Smartpointer {public : smartpointer (const smartpointer&) = Delete; smartpointer& operator= (const smartpointer&) = delete; Explicit Smartpointer (t* p= NULL) : _pointer (P) { } ~smartpointer () { delete _pointer; } t* operator-> () const { return _pointer; } t& operator* () const { return *_pointer; } t* get () const { return _pointer; } t* release () { t* p = _pointer; _pointer = NULL; return p; } void Reset (t* p = NULL) { if (p! = _pointer) { delete _pointer; _pointer = P; } } Private: t* _pointer; };
Explain the points:
(1)smartpointer similar to unique_ptr, does not support the copy construction and assignment, is the strengthening version of Auto_ptr;
Raw pointer
#include <vector> #include <iostream>using namespace Std;int main (void) { vector<int*> v; { int x = ten; V.push_back (&x); V.push_back (new int (2)); } cout << v[0] << "<< v[1] << Endl; cout << *v[0] << "<< *v[1] << Endl;}
Explain the points:
(1) When V leaves the block scope (two times the scope of the push_back), access to v[0] will be illegal pointer access, the Stack object has been refactored,v[0] The contents of the memory accessed no longer exist , although the problem output is still correct, Because the memory where the x variable resides is not being re-used;
(2) When V leaves the main scope, V has a memory leak, requires explicit delete, because the original pointer (including the class's original pointer) and int,long long such as the basic data type, do not perform destructors, memory leaks , and to display execution Delete v[0];
Raw Pointer Object
The code snippet is as follows:
#include <iostream> #include <vector> #include <utility>using namespace Std;class a{public: A () = default; A (const a& a) { cout << "copy ctor" << Endl; } A (a&& a) noexcept { cout << "Move ctor" << Endl; }; int main (void) { vector<a> Rawvec; Rawvec.reserve (ten); cout << "------------------\ n"; Rawvec.push_back (A ()); cout << "------------------\ n"; Rawvec.push_back (* (New A ())); cout << "------------------\ n"; Rawvec.push_back (Std::move (* (New A ())));
Explain the points:
(1) Rawvec.push_back (A ()); First, a temporary object is generated, since a provides a move constructor, the container calls the move constructor directly, and then the temporary object is automatically destroyed;
(2) push_back (* (new A)); first, new int () creates a heap of memory, then the dereference copies it into a vector, the management data of the vector itself is in the stack memory, and the real data is in the heap memory, which is allocated by the STL's Space Configurator. Push_back (* ()) will have a memory leak because the object placed in Push_back () is a copy of the new object, and when the vector destroys the object after the last departure from the main function, the new object is destroyed, and the original heap Memory object does not destruct. Memory leaks ;
(3) Push_back (Std::move (New A ())); first, new int () creates a heap memory, then dereference and uses Std::move to move it to the vector, but the memory (management) that is used by the new A () itself will leak ;
(4) When Rawvec leaves the main block, the destructor is called on each of its objects;
(5) because a () move construct does not do anything, the following is replaced with a as a string, assuming that the string implements the move constructor, and the strings value as a key part of the move constructor to improve efficiency;
(5.1) for Rawvec.push_back (String ("123")); Rawvec will use the mobile construct to take over the memory of "123", while the management data of its own string temporary object will be destroyed automatically;
(5.2) for Rawvec.push_back (* (New String ("123")), Rawvec will copy the memory of "123" using copy construction, and the management data of new string ("123") and "123" will be leaked;
(5.3) for Rawvec.push_back (Std::move (* (New String ("123"))), Rawvec will use the mobile construct to take over the memory of "123", while the management data of new string ("123") will be leaked , "123" does not reveal itself, but is taken over by the object in the vector;
shared_ptr generation
std::shared_ptr<int> P1 = std::make_shared<int> (); std::shared_ptr<int> p2 (new int);
Explain the points:
(1) in shared_ptr, the management information includes at least one reference count count and a pointer to the object, and for P1, the new int and the memory of the management information are applied once;
(2) and P2, the first will be a new int, and then apply for management information memory, a total of two memory applications; when multiple std::shared_ptr<int> p (new int) object assignments are involved, may lead to memory leaks;
shared_ptr two-time release problem
#include <iostream> #include <memory>using namespace Std;class a{public: A () = default; ~a () { cout << "Dtor" << Endl; }}; void Fun (Shared_ptr<a> a) {}int main (void) { A *x (new a); Fun (shared_ptr<a> (x)); cout << "-------------\ n"; Shared_ptr<a> p (x);}
Explain the points:
(1) Fun () shared_ptr has taken over the heap memory pointed to by X, and will be released, and when Shared_ptr<a> p (x), take over X point memory has been released, resulting in two releases, resulting in a segment error;
(2) using the original pointer of Shared_ptr's get (), there is also the possibility of two release issues, because shared_ptr of the get () raw pointers will be created separately, not shared;
SHARED_PTR construct the Remove device
#include <iostream> #include <memory>using namespace Std;class a{public: A () = default; ~a () { cout << "Dtor" << Endl; }}; int main (void) { A *x (new a[10]); Shared_ptr<a> A (x, [] (A *p) { delete []p; }];
Explain the points:
(1) Because shared_ptr does not directly support dynamic arrays, the default is delete p, so explicit incoming deletes are required;
(2) The stack object can sometimes need to be shared_ptr to manage, obviously we can not use the default delete, also need to pass in the delete device;
Unique_ptr memory leaks
#include <iostream> #include <memory>using namespace Std;class a{public: A () = default; ~a () { cout << "Dtor" << Endl; }}; int main (void) { unique_ptr<a> A (new a); A.release (); Unique_ptr<a[]> B (New a[1]); B.reset ();}
Explain the points:
(1) a.realase () will convert the control of the pointer, but if there is no new unique_ptr takeover, then there will be a memory leak, you should use reset for explicit memory release;
(2) a managed memory, release () will be memory leak, and B.reset will explicitly release control, and destroy memory;
(3) Unique_ptr is different from shared_ptr, and supports dynamic array directly;
"C + +" smart pointer