C++11依据使用场景的不同创建了两个新的智能指针:unique_ptr和shared_ptr、weak_ptr。
一、unique_ptr分析和使用
unique_ptr:是“独占”对象所有权语义的智能指针。
unique_ptr实现了独享被管理对象指针的概念,这意味着它可确保一个对象和其对应的资源同一时间只能被一个unique_ptr对象拥有。一旦拥有者被销毁或者变成empty或者开始拥有另一个对象的地址,先前拥有的那个对象就会被销毁,其任何相应资源也会被释放。
1、特点:
基于排他所有权模式:两个指针不能指向同一个资源。
由于独占对象的所有权,所以不提供拷贝构造函数和赋值函数重载。
提供移动构造和移动赋值函数。
为了实现单个对象和一组对象的管理,添加了删除器类型。
2、unique_ptr源代码
template<class _Ty>
struct default_deleter
{
void operator()(_Ty* ptr)const
{
delete ptr;//单个对象
}
};
template<class _Ty>
struct default_deleter<_Ty[]>
{
void operator()(_Ty* ptr)const
{
delete []ptr;//一组对象
}
};
template<class _Ty,class _Dx=default_deleter<_Ty> >
class unique_ptr
{
public:
using pointer=_Ty*;
using element_tyoe=_Ty;
using deleter_type=_Dx;
private:
pointer mPtr;
deleter_type=_Dx;
public:
unique_ptr(pointer p=nullptr):mPtr(p) { }
unique_ptr(const unique_ptr&)=delete;//删除拷贝构造
unique_ptr& operator=(const unique_ptr&)=delete;//删除赋值重载函数
~unique_ptr()
{
if(mPtr!=nullptr)
reset();
}
//移动构造函数
template<class _Ty2,class _Dx2>
unique_ptr(unique_ptr<_Ty2,_Dx2>&& other)
{
reset(other.release());
}
//移动赋值函数
template<class _Ty2,class _Dx2>
unique_ptr& operator=(unique_ptr<_Ty2,_Dx2>&& other)
{
if(this!=(unique_ptr<_Ty,_Dx>*)&other)
{
reset(other.release());
}
return *this;
}
//释放被管理对象的所有权
pointer release()
{
pointer old=mPtr;
mPtr=nullptr;
return old;
}
void reset(pointer ptr=nullptr)
{
if(mPtr!=nullptr)
{
mDeleter(mPtr);
}
mPtr=ptr;
}
void swap(unique_ptr& other)
{
std::swap(this->mPtr,other.mPtr);
}
pointer get()const
{
return mPtr;
}
//返回用于析构被管理对象的删除器
_Dx& get_deleter()
{
return m_Deleter;
}
const _Dx& get_deleter()const
{
return m_Deleter;
}
explicit operator bool()const
{
return static_cast<bool>(mPtr!=nullptr);
}
_Ty& operator*()const
{
return *mPtr;
}
pointer operator->()const
{
return get();
}
};
template<class _Ty,class _Dx>
class unique_ptr<_Ty[],_Dx>
{
public:
using pointer=_Ty*;
using element_type=_Ty;
using deleter_type=_Dx;
private:
pointer mPtr;
deleter_type mDeleter;
public:
unique_ptr(pointer p=nullptr):mPtr(p)
{ }
unique_ptr(const unique_ptr&)=delete;
unique_ptr& operator=(const unqiue_ptr&)=delete;
//移动构造
template<class _Ty2,class _Dx2>
unique_ptr(unique_ptr<_Ty,_Dx2>&& other)
{
if(this!=(unique_ptr<_Ty,_Dx>*>& other)
{
reset(other.release());
}
}
//移动赋值
template<class _Ty2,class _Dx2>
unique_ptr& operator=(unique_ptr<_Ty2,_Dx2>&& other)
{
if(this!=(unique_ptr<_Ty,_Dx>*)& other)
{
reset(other.release());
}
return *this;
}
~unique_ptr()
{
if(mPtr!=nullptr)
reset();
}
//释放被管理对象的所有权
pointer release()
{
pointer old=mPtr;
mPtr=nullptr;
return old;
}
void reset(pointer ptr=nullptr)
{
if(mPtr!=nullptr)
mDeleter(mPtr);
mPtr=ptr;
}
void swap(unique_ptr& other)
{
std::swap(this->mPtr,other.mPtr);
}
pointer get()const
{
return mPtr;
}
//返回用于析构被管理对象的删除器
_Dx& get_deleter()
{
return mDeleter;
}
const _Dx& get_deleter()const
{
return mDeleter;
}
explicit operator bool()const
{
return static_cast<bool>(mPtr!=nullptr);
}
_Ty& operator*()const
{
return *mPtr;
}
pointer operator->()const
{
return get();
}
_Ty& operator[](std::size_t i)const
{
return get()[i];//mPtr[i]
}
};
3、辅助函数
(1)get返回指向被管理对象的指针;
(2)reset替换被管理对象;
(3)release释放被管理对象的所有权;
(4)swap交换被管理对象;
(5)operator[] bool() const检查是否有关联的被管理对象;
(6)重载operator*,operator->,访问被管理对象。
4、不能拷贝构造和左值赋值
5、可以移动构造和移动赋值
6、管理动态数组
7、使用unique_ptr总结
unique_ptr在要表达“专属所有权”的语义时使用,即unique_ptr指针永远拥有其指向的对象,所以unique_ptr是一个move_only类型,一个unique_ptr指针是无法被复制的,只能将所有权在两个unique_ptr指针之间转移,转移完成后原来的unque_ptr将被设为nullptr。
(1)语义简单,即当你确定要使用的指针是不是被共享所有权的时候,认选unique_ptr独占式所有权,当确定要被共享的时候可以转换成shared_ptr;
(2)unique_ptr效率比shared_ptr高,不需要维护引用计数块;
(3)在需要时可以将unique_ptr转换成shared_ptr。