智能指针的作用是防止new出来(处于堆上)的对象因指针操作失误没有及时delete而导致内存泄露。
智能指针原理是用一个计数类RefCount存储要指向的地址和指向该地址的指针数,根据指针数来决定是否应该delete申请的内存。
如图:
SmartPtr
当将一个new出来的内存地址赋值给SmartPtr指针ptr1时,会用一个RefCount类m_Ptr存储这个内存地址,并将m_iCount设为1。
SmartPtr
当其他SmartPtr指针ptr2指向这个指针的时候,并不是单单将new出的目标地址赋给ptr2指针,而是将整个ptr1的RefCount(目标地址和指针计数器)传到ptr2,然后m_iCount会加1,表示多了一个指针指向这个地址。
ptr1=new CMyObject("second object");
当ptr1将指向新地址的时候,会将之前RefCount的m_iCount减1,表示少了一个指针指向之前地址,如果旧地址的计数器m_iCount为0,则表示已经没有指针指向这个地址了,将会自动调用delete释放旧的地址。
如图:当多个Smart指针指向一个地址的时候,各指针共享一个RefCount类对象,m_iCount记录指针数。
- #include <iostream>
- using namespace std;
- template<class T>class RefCount;
- template <class T> class SmartPtr
- {
- private:
- RefCount<T> *m_RefCount;
- public:
- SmartPtr(T* Ptr)
- {
- m_RefCount=new RefCount<T>(Ptr);
- m_RefCount->InitCount();
- }
- SmartPtr(RefCount<T>* Ptr)
- {
- Ptr->AddCount();
- m_RefCount=Ptr;
- }
- ~SmartPtr()
- {
- m_RefCount->Destroy();
- }
- RefCount<T>* GetPtr()
- {
- return m_RefCount;
- }
- SmartPtr<T>& operator = (T* Ptr)
- {
- if (this->m_RefCount!=NULL)
- {
- this->m_RefCount->Destroy();
- }
- m_RefCount=new RefCount<T>(Ptr);
- m_RefCount->InitCount();
- return *this;
- }
- SmartPtr<T>& operator = (SmartPtr<T>& Ptr)
- {
- if (this->m_RefCount!=NULL)
- {
- this->m_RefCount->Destroy();
- }
- Ptr.m_RefCount->AddCount();
- this->m_RefCount=Ptr.m_RefCount;
- return Ptr;
- }
- T& operator * (){return *(m_RefCount->m_Ptr);};
- };
- template<class T>class RefCount
- {
- friend class SmartPtr<T>;
- private:
- T* m_Ptr;
- int m_iCount;
- public:
- void AddCount()
- {
- m_iCount++;
- }
- void InitCount()
- {
- m_iCount=1;
- }
- void Destroy()
- {
- m_iCount--;
- if (m_iCount==0)
- {
- delete m_Ptr;
- }
- }
- RefCount(T* ptr)
- {
- m_Ptr=ptr;
- }
- ~RefCount()
- {
- }
- T* GetPtr()
- {
- return m_Ptr;
- }
- };
- class CMyObject
- {
- char *name;
- public:
- CMyObject(char* aname){name=aname;printf("create %s\n",name);}
- ~CMyObject(){printf("delete %s\n",name);}
- };
- void main()
- {
- SmartPtr<CMyObject> ptr1(new CMyObject("1"));
- SmartPtr<CMyObject> ptr2=new CMyObject("2");
- ptr1=ptr2;
- ptr1=new CMyObject("3");
- ptr2=SmartPtr<CMyObject>(new CMyObject("4"));
- ptr2=NULL;
- }