Intelligent pointer implementation and intelligent pointer implementation
When I saw the iterator, I thought about how to summarize the knowledge of smart pointers.
I have implemented three smart pointers: auto_ptr, scoped_ptr, and shared_ptr. They are named based on the smart pointer in the boost library.
What is smart pointer? Smart pointers can help you automatically release the memory when you forget to release the new memory. This can effectively avoid Memory leakage. For example, when an exception occurs, you can jump to the next hop... The memory should be released. If you keep holding it, it will cause memory leakage. The smart pointer is RAII (resource allocation is initialization) A typical application uses class constructor and destructor to open up and release memory. Smart pointers cannot be completely called pointers, it is a type used to manage the release of pointers. When out of scope, it will go back to the memory for release. To make the smart pointer more like a pointer, You need to reload the operators: for example, if you reference the above Code as part of auto_ptr, but the obvious problem is that the constructor is not copied. When you do not write a copy constructor and use the default copy constructor, this kind of statement is very dangerous. How can this problem be solved when it involves the in-depth copy? Next let's talk about it !~ Auto_ptr -- automatically release the pointer (big pitfall goods): After the assignment is copied, the previous object is left empty. This completes the release only once (when a copy occurs, the two pointers release the same space to which the Pointer Points !) Scoped_ptr -- "guard --" anti-Copy ": the simple and crude use of pravate does not give you access permissions and does not allow copying (since the copy will fail, it will be okay if you don't copy it ?) Shared_ptr -- share -- reference counting: the pointer reference counting method is used, neither common type nor static variables are used, it is to use a pointer (in fact, the most recommended use is to copy the pointer, that is, do not copy the copy, you must copy and then share the pointer) to paste the code!
1 class AutoPtr 2 {3 public: 4 AutoPtr (T * ptr = NULL) 5: _ ptr (ptr) 6 {7} 8 AutoPtr (AutoPtr & ap) 9: _ ptr (ap. _ ptr) 10 {11 ap. _ ptr = NULL; 12} 13 ~ AutoPtr () 14 {15 delete _ ptr; 16} 17 AutoPtr & operator = (AutoPtr & ap) 18 {19 if (_ ptr! = Ap. _ ptr) 20 {21 if (NULL = _ ptr) 22 {23 _ ptr = ap. _ ptr; 24 ap. _ ptr = NULL; 25} 26 else27 {28 delete _ ptr; 29 _ ptr = ap. _ ptr; 30 ap. _ ptr = NULL; 31} 32} 33 return * this; 34} 35 T & operator * () 36 {37 return * _ ptr; 38} 39 T * operator-> () 40 {41 return _ ptr; 42} 43 T * GetPtr () 44 {45 return _ ptr; 46} 47 private: 48 T * _ ptr; 49}; 50 51 52 53 void test1 () 54 {55 AutoPtr <int> ap1 = new int; // supports strong conversion (here, the int * generated by new is strongly converted to the auto_ptr pointer, that is, the int * is used to construct a temporary auto_ptr variable and then assigned a value.) 56 AutoPtr <int> ap2 = new int; 57 // AutoPtr <int> ap3 (ap1); // be careful, copy 58 AutoPtr in depth <int> mask; 59 mask = ap1; 60 ap2 = ap1; 61/* int * p1 = new int; 62 int * p2 = new int; 63 delete p1; 64 delete p2; */65}
PS: the longest-commented AutoPtr <int> ap1 = new int; if you do not want this to happen, useExplicit keywords
I posted the test cases ~ The implementation of auto_ptr is still very simple, but it is too difficult to use ~
Next, the smart pointer scoped_ptr for anti-copy
1 #include<iostream> 2 using namespace std; 3 4 5 6 template<class T> 7 class ScopedPtr 8 { 9 public:10 ScopedPtr(T* ptr=NULL)11 :_ptr(ptr)12 {13 }14 ~ScopedPtr()15 {16 if (_ptr)17 {18 delete _ptr;19 }20 }21 T* operator ->()22 {23 return _ptr;24 }25 T& operator *()26 {27 return *_ptr;28 }29 T* GetPtr()30 {31 return _ptr;32 }33 34 private:35 ScopedPtr(ScopedPtr& sp)36 {37 38 }39 ScopedPtr& operator=()40 {41 42 }43 private:44 T* _ptr;45 };46 47 48 49 void test1()50 {51 52 ScopedPtr<int> sp1 = new int(1);53 ScopedPtr<int> sp2 = new int(2);54 ScopedPtr<int> sp3(sp1);55 }
If you execute this code, a compilation error will be reported. Because the copy structure is put in a private member, it cannot be used, and the implementation is very simple. You can just drop all the copy items to private.
Next we will share the shared_ptr pointer.
1 #include<iostream> 2 using namespace std; 3 template<class T> 4 class SharedPtr 5 { 6 public: 7 SharedPtr(T* ptr) 8 :_ptr(ptr) 9 ,_pCount(new int(1))10 {11 12 }13 SharedPtr(SharedPtr& sp)14 :_ptr(sp._ptr)15 ,_pCount(sp._pCount)16 {17 (*_pCount)++;18 }19 ~SharedPtr()20 {21 if (--(*_pCount) == 0)22 {23 delete _ptr;24 delete _pCount;25 }26 }27 SharedPtr& operator=(SharedPtr& sp)28 {29 if (_ptr != sp._ptr)30 {31 if (NULL == _ptr)32 {33 _ptr = sp._ptr;34 _pCount = sp._pCount;35 }36 else37 {38 _Release();39 }40 }41 return *this;42 }43 T& operator*()44 {45 return *_ptr;46 }47 T* operator->()48 {49 return _ptr;50 }51 protected:52 void _AddRef()53 {54 ++(*_pCount);55 }56 void _Release()57 {58 if (--(*_pCount) == 0)59 {60 delete _ptr;61 delete _pCount;62 _ptr = NULL;63 _pCount = NULL;64 }65 }66 private:67 T* _ptr;68 int* _pCount;69 };
The reference count is implemented by pointers. Static variables are used at the beginning, but there is a problem when we declare
1 SharedPtr<int> s = new int(20);2 SharedPtr<int> s1=new int (30);
Because the stored values are different, the reference count should not increase. However, because static variables are used, all the objects in this class use this reference count, and the reference count will be added, this is wrong.
Using pointers to open up a unique space for counting management is obviously what we need. It would be better to leave the delete pointer blank during structure analysis ~ So with the Release function