The meaning of smart pointer
In C + +, new and delete are the keywords to apply for and destroy heap memory. After applying for heap memory, programmers often forget to delete to release heap memory, which is easy to cause a phenomenon - memory leakage, that is, a piece of heap memory is not released after being applied, so that other programs cannot use this heap memory, resulting in a waste of heap memory, It reduces the development efficiency of C + +. In java and other languages, there is only the new keyword, but not the delete keyword. This is because of the memory recycling mechanism of java language. Due to the previous extreme pursuit of code running efficiency by C + +, this mechanism has not been introduced. But. With the release of C11 standard, smart pointer is gradually accepted by everyone. Although it will reduce the efficiency, it also greatly reduces the memory leakage and other problems encountered by developers in the development process.
The smart pointer is not a pointer, but a kind of template. The object instantiated through the smart pointer can automatically release the memory when the object is destroyed, instead of being released manually by the developer.
Realization of intelligent pointer
For the generation and destruction of an object, there are the following steps:
Object generation:
- Open up heap memory;
- Call the constructor.
Destruction of objects:
- Call the destructor;
- Free memory;
According to the important characteristics of object destruction: automatically call the destructor. We only need to write the delete memory release function to the destructor. When the object is destroyed, the system can automatically release heap memory, so as to avoid memory leakage and other problems.
Intelligent pointer under C++11 standard
C + + provides developers with two types of smart pointers:
- Smart pointer with reference count
- Smart pointer without reference count
They are auto_ptr,unique_ptr,shared_ptr,weak_ptr and other smart pointers. Where auto_ptr is a smart pointer introduced in c98 standard, and the remaining smart pointers were later introduced into C + + with reference to the implementation of smart pointers in boost library. They all exist in the memory library, so when using smart pointers
auto_ptr
auto_ptr existed in the STL library as early as the release of c98 standard, but now it has been abandoned due to various performance problems. Study auto first_ Source code of PTR:
template<class _Ty> class auto_ptr { // wrap an object pointer to ensure destruction public: typedef auto_ptr<_Ty> _Myt; typedef _Ty element_type; // Constructor explicit auto_ptr(_Ty *_Ptr = 0) _THROW0() : _Myptr(_Ptr) { // construct from object pointer } // Copy the constructor and call the release method auto_ptr(_Myt& _Right) _THROW0() : _Myptr(_Right.release()) { // construct by assuming pointer from _Right auto_ptr } // Assignment operator function, call release method template<class _Other> _Myt& operator=(auto_ptr<_Other>& _Right) _THROW0() { // assign compatible _Right (assume pointer) reset(_Right.release()); return (*this); } // Destructor ~auto_ptr() _NOEXCEPT { // destroy the object delete _Myptr; } // Pointer dereference operator overload _Ty& operator*() const _THROW0() { // return designated value #if _ITERATOR_DEBUG_LEVEL == 2 if (_Myptr == 0) _DEBUG_ERROR("auto_ptr not dereferencable"); #endif /* _ITERATOR_DEBUG_LEVEL == 2 */ return (*get()); } // Pointer overload _Ty *operator->() const _THROW0() { // return pointer to class object #if _ITERATOR_DEBUG_LEVEL == 2 if (_Myptr == 0) _DEBUG_ERROR("auto_ptr not dereferencable"); #endif /* _ITERATOR_DEBUG_LEVEL == 2 */ return (get()); } // Get method -- get pointer address _Ty *get() const _THROW0() { // return wrapped pointer return (_Myptr); } // Deprive original auto_ptr's ownership of the pointer gives the current auto_ptr ownership of pointer _Ty *release() _THROW0() { // return wrapped pointer and give up ownership _Ty *_Tmp = _Myptr; _Myptr = 0; return (_Tmp); } // Destroys the specified object and stores the new pointer void reset(_Ty *_Ptr = 0) { // destroy designated object and store new pointer if (_Ptr != _Myptr) delete _Myptr; _Myptr = _Ptr; } private: _Ty *_Myptr; // the wrapped object pointer };
Shared_ptr
shared_ The biggest difference between PTR and other smart pointers is that reference counting is added, that is, the use object of a resource can be counted. If the use object of this resource becomes 0, this block of memory needs to be deleted. But usually with weak_ptr use.
The code is as follows:
ount; }; trmplate<class T> class Shard_ptr{ public: Shared_ptr(T* p=0):_ptr(p) { cnt=new Counter; if(p) { cnt->shardCount=1; } } ~Shared_ptr() { release(); } Shared_ptr(Shared_ptr<T> const &src) //copy construction { _ptr=src._ptr; //Of the original shared object (src.cnt)->shardCount++; } Shared_ptr(WeakPtr<T>&const w) { //Copy weakptr object pointer _ptr=w._ptr; (w.cnt)->sharedCount++; cnt=w.cnt; } Shared_ptr<T>& operator=(Shared_ptr<T>& src) { //Prevent self reference if(this!=&src) { //Release ownership of source managed objects release(); (src.cnt)->sharedCount++; cnt=src.cnt; _ptr=src._ptr; } return *this; } T& operator*() { return* _ptr; } T* operator->() { return _ptr; } friend class WeakPtr<T>; protected: //Release the ownership of the source object. If the count is 0, the memory will be reclaimed void release() { cnt->shardCount--; if(cnt->shardCount<1) { delete _ptr; if(cnt->weakCount<1) { delete cnt; cnt=NULL; } } } private: T* _ptr; Counter* cnt; };
weak_ptr
weak_ For shareptr_ PTR, whose copy constructor is shared_ PTR and weak_ptr object is constructed without overloading * and - >, and lock() is used to get an available object. weak_ptr() does not have the right to use memory, so it cannot use resources directly. lock() is usually used to generate a shared_ PTR.
template<class T> class WeakPtr { public: WeakPtr() { _ptr=0; cnt=new Counter(); } WeakPtr(Sharedptr<T>& src):_ptr(src._ptr),_cnt(src.cnt) { cnt.weakCount++; } WeakPtr(WeakPtr<T>& src):_ptr(src._ptr),cnt(src.cnt) { cnt.weakCount++; } ~WeakPtr() { release(); } WeakPtr<T>& operator=(WeakPtr<T>& src) { if(this!=*src) { //Release the original management object release(); cnt=src.cnt; cnt->weakCount++; _ptr=src._ptr; } return *this; } WeakPtr<T>& operator=(WeakPtr<T>& src) { if(this!=*src) { release(); cnt=src.cnt; cnt->shardCount++; _ptr=src._ptr; } return *this; } Sharedptr<T> lock() { //Convert weakptr to sharedptr return Sharedptr<T>(*this); } bool expired() { if(cnt) { if(cnt->shardCount>0) { return false; } } return true; } friend class Sharedptr<T>; protected: void release() { if(cnt) { cnt->weakCount--; if(cnt->weakCount<1 && cnt->s<1) { cnt=NULL; } } } private: T* _ptr; Counter* cnt; };
Introduce weak_ptr is to solve the problem of strong intelligent pointer Shared_ptr may cause cross reference, so that the counter will never decrease to 0, so that the resource cannot be released. Therefore, strong smart pointers are used to define objects, and weak smart pointers are used to define objects.