智能指针的三种常见写法:
一、最开始的原始写法,原始写法可以理解为指针转移的方法。
template<typename T>
class AutoPtr
{
public:
AutoPtr()
:_ptr(NULL)
{}
AutoPtr(T* ptr)
:_ptr(ptr)
{}
~AutoPtr()
{
if (_ptr)
{
delete _ptr;
_ptr = NULL;
}
}
AutoPtr<T>(AutoPtr<T>& ap)
: _ptr(ap._ptr)
{
ap._ptr = NULL;
}
AutoPtr<T>& operator = (AutoPtr<T>& ap)
{
if (this != &ap)
{
delete _ptr;
_ptr = ap._ptr;
ap._ptr = NULL;
}
return *this;
}
T& operator*()
{
return *_ptr;
}
T* GerPtr()
{
return _ptr;
}
private:
T* _ptr;
};
二、演变为后来的scoped写法,又可以称作守卫写法。该写法相对于原始写法的优点在于不让使用拷贝构造和运算符的重载,这样就避免了深浅拷贝的指针问题。做法是把拷贝构造、运算符的重载定声明出来而不定义,并且用protected保护起来。scoped写法是引用的boost库。有兴趣的可以去了解一下这个东西,背后还是有很多故事的,在这我就不多说啦。
template<class T>
class scopedPtr
{
public:
scopedPtr()
:_ptr(NULL)
{}
scopedPtr(T* ptr)
:_ptr(ptr)
{}
~scopedPtr()
{
if (_ptr)
{
delete _ptr;
_ptr = NULL;
}
}
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
T* GetPtr()
{
return _ptr;
}
protected: //加上protected可以防止使用者在类之外定义拷贝构造和运算符的重载函数
scopedPtr<T>(const scopedPtr<T>& sp); //不让使用者使用拷贝,可以防止拷贝,所以只声明不定义
scopedPtr<T>& operator=(const scopedPtr<T>& sp);
private:
T* _ptr;
};
三、sharedPtr写法
这种方法考虑了深浅拷贝问题并且引用了引用计数器来解决浅拷贝的问题,比较完善的实现了智能指针想要实现的功能。
template<class T>
class SharePtr
{
public:
SharePtr(T* ptr)
:_ptr(ptr)
, _pCount(new int(1))
{}
//SharePtr(Shar)
// :_ptr(sp._ptr)
//{
// *_pCount = 1;
//}
~SharePtr()
{
if (_ptr)
{
if (--(*_pCount) == 0)
{
delete _ptr;
delete _pCount;
_ptr = NULL;
_pCount = NULL;
}
_ptr = NULL;
}
}
SharePtr<T>(const SharePtr<T>& sp)
{
_ptr = sp._ptr;
_pCount = sp._pCount;
++(*_pCount);
}
SharePtr<T>& operator=(const SharePtr<T>& sp)
{
if (this != &sp)
{
if (--(*_pCount) == 0) //这里要分清楚是谁减一,逻辑需要分析清楚
{
delete _ptr;
delete _pCount;
_ptr = NULL;
_pCount = NULL;
}
_ptr = sp._ptr;
_pCount = sp._pCount;
++(*_pCount);
}
return *this;
}
private:
T* _ptr;
int* _pCount;
};
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。