1. Implementation version v3
- Reference counting techniques:
The reference count needs to be stored in the referenced resource object. A resource object corresponds to a reference count. When the reference count is 0, the resource object can be destroyed.
Need to modify the following functions to implement the counting function:
- Constructors that receive different object types: This constructor implementation is relatively simple, just add 1 to the reference count
- Destructor: In the implementation of the destructor, the delete operation cannot be performed directly, but the reference count needs to be decremented by 1. When the reference count is 0, the delete operation can be performed.
- Copy constructor: The implementation of the copy constructor, the underlying pointer is shared, and then the reference count is incremented by 1.
- Assignment operator: The implementation of the assignment operation is a little more complicated. It involves adding 1 to the reference count of the newly pointed object, decrementing the reference count of the original pointed object by 1, and destroying the original pointed object if necessary. It is worth noting here that the implementation of our new assignment operation no longer needs the if (this == &other) return *this; statement to deal with the situation of self-assignment. Readers can analyze the implementation of our new assignment operation by themselves. There is no need to handle self-assignment through an if statement.
- Reference counting base class
Generally, according to the object-oriented design method, we will abstract the relevant content of reference count management into a base class, so that any resource class that is expected to be referenced by smart pointers only needs to inherit this class.
- Header file smartpointer.h
/* * file name : smartpointer.h * desp : smart pointer version v3 */ #ifndef __SMARTPOINTER_H__ #define __SMARTPOINTER_H__ template <typename T> // Define the smart pointer class as a template class class SmartPointer { public: // default constructor SmartPointer():mPointer(NULL) {std::cout <<"Create null smart pointer."<< std::endl;} // Constructors that accept different object types SmartPointer(T *p):mPointer(p) { std::cout <<"Create smart pointer at "<<static_cast<const void*>(p)<<std::endl; /* The smart pointer points to class T, and the reference count is incremented by 1*/ if (mPointer) mPointer->incRefCount(); } // destructor ~SmartPointer(){ std::cout << "Release smart pointer at "<<static_cast<const void*>(mPointer)<<std::endl; // Implement the automatic destruction mechanism of memory resources if (mPointer && mPointer->decRefCount()==0) delete mPointer; } // copy constructor SmartPointer(const SmartPointer &other):mPointer(other.mPointer) { std::cout <<"Copy smart pointer at "<<static_cast<const void*>(other.mPointer)<<std::endl; // increment the reference count by 1 if(mPointer) mPointer->incRefCount(); } // assignment operator SmartPointer &operator = (const SmartPointer &other) { T *temp(other.mPointer); // The new pointer to the object, the reference count value is incremented by 1 if (temp) temp->incRefCount(); // The original point to the object, the reference count value is decremented by 1, if the reference count is 0 after decrementing 1, the original resource object is destroyed if (mPointer && mPointer->decRefCount()==0) delete mPointer; // smart pointer points to the new resource object mPointer = temp; return *this; } private: T *mPointer; // Point to the actual memory resource corresponding to the smart pointer, define the internal resource pointer type according to the automatic parameter deduction rules }; /*Reference count base class*/ class RefBase { public: RefBase() : mCount(0){ } void incRefCount(){ mCount++; } int decRefCount(){ return --mCount; } // Debug interface, return the current reference count of the object int getRefCount () { return mCount; } virtual ~RefBase(){ } private: int mCount; }; #endif // __SMARTPOINTER_H__
- Test file sptestcase3.cpp
/* * file name : sptestcase3.cpp * desp : smart pointer test code case3 test the reference counting function of smart pointer */ #include <iostream> #include "smartpointer.h" /* SomeClass class inherited from reference counting base class */ class SomeClass: public RefBase{ public: SomeClass(){std::cout << "SomeClass default constructor !"<<std::endl;} ~SomeClass(){std::cout << "SomeClass deconstructor !"<<std::endl;} }; void testcase3(void) { SomeClass *pSomeClass = new SomeClass(); //1 SmartPointer<SomeClass> spOuter = pSomeClass; std::cout << "SomeClass Ref Count (" << pSomeClass->getRefCount() << ") outer 1."<< std::endl; { // inner block SmartPointer<SomeClass> spInner = spOuter; std::cout << "SomeClass Ref Count (" << pSomeClass->getRefCount() << ") inner."<< std::endl; } std::cout << "SomeClass Ref Count (" << pSomeClass->getRefCount() << ") outer 2."<< std::endl; // delete pSomeClass ; no delete operation is required and cannot be performed! std::cout << "new another SomeClass class for spOuter."<< std::endl; SmartPointer<SomeClass> spOuter2 = new SomeClass(); spOuter = spOuter2;// SomeClass from new at 1 will be automatically released } int main(void) { testcase3(); return 0; }
Result analysis
- The v3 version basically implements the function of smart pointers, and the next step can improve the functions as pointers: dereference, null, comparison operations
2. Knowledge point checking and filling vacancies
- wild pointer