STL中的auto_ptr是不带有引用计数的,因此一个实体只能被一个auto_ptr对象拥有。由于这样的限制,才会提出auto_ptr在拷贝构造或赋值操作时转移指针所有权的处理方法。向智能指针中添加引用计数可以完全避免“所有权转移”带来的错觉,从而规范指针不安全行为,让智能指针真正Smart。
内建指针和引用计数分别占有一块堆内存,分别用T* ptr和int* pCnt来保存它们的地址。当然,也可以将它们摆放到相邻的位置上,不过这会增加实现的难度,不便于我们理解引用计数的实现。SmartPtr的代码如下所示:
// SmartPtr
template<class T>
class SmartPtr
{
public:
SmartPtr(T* src):ptr(src),pCnt(new int(1))
{
}
SmartPtr(const SmartPtr<T>& src):ptr(src.ptr),pCnt(src.pCnt)
{
++(*pCnt);
}
SmartPtr<T>& operator=(const SmartPtr<T>& rhs)
{
if(ptr != rhs.ptr)
{
Release();
ptr = rhs.ptr;
pCnt = rhs.pCnt;
++*pCnt;
}
return (*this);
}
T* operator->()
{
return ptr;
}
const T* operator->()const
{
return ptr;
}
T& operator*()
{
return (*ptr);
}
const T& operator*()const
{
return (*ptr);
}
~SmartPtr()
{
Release();
}
private:
T* ptr;
int *pCnt;
void Release()
{
if(--*pCnt == 0)
{
delete ptr;
delete pCnt;
}
}
};
在main函数中,编写以下代码进行测试:
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include"SmartPtr.h"
class UserInfo
{
public:
UserInfo(const char* strName, const char* strNation)
{
strcpy_s(this->strName,strName);
strcpy_s(this->strNation,strNation);
}
void displayUser()
{
printf_s("我是%s,来自%s\n",strName,strNation);
}
~UserInfo()
{
}
private:
char strName[10];
char strNation[10];
};
int main()
{
UserInfo* pui = new UserInfo("罗纳尔多","巴西");
SmartPtr<UserInfo> tpui(pui);
SmartPtr<UserInfo> tpui2(tpui);
tpui2->displayUser();
tpui = tpui2;
SmartPtr<UserInfo> tpui3(new UserInfo("齐达内","法国"));
tpui2 = tpui3;
tpui2->displayUser();
system("pause");
return 0;
}
输出结果为:
参考资料: