Implementation of smart Pointers-implementation and principle of reference counting
I. When smart pointers are programmed in C ++, when there are pointer members in the class, there are generally two ways to manage pointer members: one is to manage them in a value-type way, each class Object retains a copy of the object to which the Pointer Points. Another more elegant way is to use a smart pointer to share the object to which the Pointer Points. A common implementation technology of smart pointer is the use of reference count ). The smart pointer class associates a counter with the object to which the class points. The reference counting class tracks how many objects in the class share the same pointer. Each time a new object of the class is created, the pointer is initialized and the reference count is set to 1. when an object is created as a copy of another object, copy the constructor to copy the pointer and add the corresponding reference count. when an object is assigned a value, the value assignment operator reduces the reference count of the object indicated by the left operand (if the reference count is reduced to 0, delete the object), and increase the reference count of the object indicated by the right operand. when calling the destructor, The Destructor reduces the reference count (if the reference count is reduced to 0, the basic object is deleted ).II. General implementation of smart pointers
Smart pointers are usually implemented using class templates. Simulate various behaviors of class pointers. However, its most important role is to manage class pointer members to prevent the appearance of suspension pointers.
template
class SmartPointer{ public: SmartPointer(T *t):pt(t){} T& operator *(){ return *pt; } T* operator ->() { return pt; } private: T *pt; };
Iii. Implementation of reference count
To implement reference counting, we define a _ counter class to record the number of references and set all the members of the _ counter class to private, because other types do not need to access _ counter, only SmartPointer can operate on it, And SmartPointer will be set as its friend Meta class.
class _counter{ template
friend class SmartPointer; _counter(int u):use(u){} ~_counter(){} int use; };
In the SmartPointer class, the _ counter pointer is retained.
Template
Class SmartPointer {public: SmartPointer (T * t): pc (new _ counter (1) {cout <"SmartPointer: SmartPointer () invoded use is:" <
Use <
Pt = t;} SmartPointer (SmartPointer
& Rhs) {this-> pc = rhs. pc; this-> pt = rhs.pt; this-> pc-> use ++; cout <"SmartPointer copy invoked use is:" <
Use <
Use --; cout <"SmartPointer ::~ SmartPointer () invoded use is: "<
Use <
Use = 0) {delete pt; delete pc;} SmartPointer
& Operator = (SmartPointer
Rhs) {if (rhs = * this) {return * this ;}
if
(--pc->use==0){
delete
pt;
delete
pc;
}
This-> pt = rhs.pt; this-> pc = rhs. pc; this-> pc-> use ++; cout <"SmartPointer: operator = () invoked use is:" <
Use <
For example, we have a HasPtr class, and one of its class members is the pointer * p.
Class HasPtr {public: HasPtr (int val): value (val), p (new int (3) {cout <"HasPtr: HasPtr () invoked" <
If the call is as follows:
HasPtr *php = new HasPtr(3); SmartPointer
psp(php); SmartPointer
npsp(psp);
We now have two smart pointer objects pointing to the same HasPtr object. The model is as follows:
_ Counter's use Member (reference count) is 2.
Iv. Test
int main(void) { HasPtr *php = new HasPtr(3); SmartPointer
psp(php); SmartPointer
npsp(psp); SmartPointer
nnpsp = npsp; return 0; }
Using the gcc compiler, the running result is as follows:
Find another implementation:
<喎?http: www.bkjia.com kf ware vc " target="_blank" class="keylink">
VcD4KPHByZSBjbGFzcz0 = "brush: java;"> # include
# Include
Using namespace std; # define SAFE_DELETE (p) if (p) {delete p; p = NULL;} class KRefCount {public: KRefCount (): m_nCount (0) {} public: unsigned AddRef () {return InterlockedIncrement (& m_nCount);} unsigned Release () {return InterlockedDecrement (& m_nCount);} void Reset () {m_nCount = 0;} private: unsigned long m_nCount;}; template
Class SmartPtr {public: SmartPtr (void): m_pData (NULL) {m_pReference = new KRefCount (); m_pReference-> AddRef ();} SmartPtr (T * pValue ): m_pData (pValue) {m_pReference = new KRefCount (); m_pReference-> AddRef ();} SmartPtr (const SmartPtr
& Sp): m_pData (sp. m_pData), m_pReference (sp. m_pReference) {m_pReference-> AddRef ();}~ SmartPtr (void) {if (m_pReference & m_pReference-> Release () = 0) {SAFE_DELETE (m_pData); SAFE_DELETE (m_pReference);} inline T & operator *() {return * m_pData;} inline T * operator-> () {return m_pData;} SmartPtr
& Amp; operator = (const SmartPtr
& Sp) {if (this! = & Sp) {if (m_pReference & m_pReference-> Release () = 0) {SAFE_DELETE (m_pData); SAFE_DELETE (m_pReference);} m_pData = sp. m_pData; m_pReference = sp. m_pReference; m_pReference-> AddRef ();} return * this;} SmartPtr
& Operator = (T * pValue) {if (m_pReference & m_pReference-> Release () = 0) {SAFE_DELETE (m_pData); SAFE_DELETE (m_pReference);} m_pData = pValue; m_pReference = new KRefCount; m_pReference-> AddRef (); return * this;} T * Get () {T * ptr = NULL; ptr = m_pData; return ptr ;} void Attach (T * pObject) {if (m_pReference-> Release () = 0) {SAFE_DELETE (m_pData); SAFE_DELETE (m_pReference);} m_pData = pObject; m_pReference = new KRefCount; m_pReference-> AddRef ();} T * Detach () {T * ptr = NULL; if (m_pData) {ptr = m_pData; m_pData = NULL; m_pReference-> Reset ();} return ptr;} private: KRefCount * m_pReference; T * m_pData ;}; class CTest {public: CTest (int B): a (B) {} private: int a ;}; int main () {SmartPtr
PSmartPtr1 (new CTest (10); SmartPtr
PSmartPtr2 (new CTest (20); pSmartPtr1 = pSmartPtr2 ;}