unique_ptr智能指针
为什么说unique_ptr是一个独享指针,体现在哪里?
unique_ptr对象始终是关联的原始指针的唯一所有者,因此在其析构函数中它直接删除关联的指针,不需要任何参考计数。我们无法复制unique_ptr对象,它只能移动。
示例:
unique_ptr<int>s_pa(new int(88));
unique_ptr<int>s_pb=move(s_pa);
这里是显式的所有权转移,C++11标准中才有的
unique_ptr的特点:
- 不允许隐式构造
- 不能将同一个裸指针赋值给多个智能指针
- 不允许普通的拷贝构造和等号运算符重载(auto_ptr允许这种操作,是直接将原智能指针给置空了,而这里则直接不允许这种操作)
- 允许对即将死亡的对象做拷贝构造和等号运算符重载 (这里还是会将原来的智能指针置空,但因为是将亡值,不会造成任何影响)
- 消除资源直接使用deleter()(删除器:会自动区分是数组还是普通指针)
- unique_ptr实际上是对auto_ptr的优化,区别不大,大部分功能都相同
创建空对象:
Munique_ptr<int> u_p1;
//因为没有与其关联的裸指针,所以是空的
创建对象:
int* p = new int(10);
Munique_ptr<int> u_p1(p);
Munique_ptr<int> u_p2(p);//报错,每个unique_ptr对象都是裸指针的唯一所有者,不能共享
判空:
判空判断的是unique_ptr对象有没有与其关联的裸指针,有,则不为空,否则,则空
operator bool()const//是否还拥有资源
{
return _ptr != NULL;
}
可以对将亡值进行拷贝构造和等号运算符赋值
示例:
Munique_ptr<int> fun(Munique_ptr<int>& ptr)
{
cout << *ptr << endl;
return Munique_ptr<int>(new int(10));//new int(10)就是一个将亡值
}
Munique_ptr(const Munique_ptr&& src)
//&&是右值引用,对于将亡值的引用,必须使用右值引用
{
if (this == &src)
{
return;
}
_ptr = src._ptr;
src._ptr = NULL;//将 将亡值置空
}
Munique_ptr& operator=(Munique_ptr&& src)
{
if (this == &src)//防止自赋值
{
return *this;
}
delete _ptr;//这里还没有调用析构,在赋值之前,需要先delete指针
_ptr = src._ptr;
src._ptr = NULL;
return *this;
}
注意:对于将亡值的引用都是用右值引用
获取unique_ptr的内部指针:
T* get()
{
return _ptr;
}
释放unique_ptr对裸指针的所有权智能指针并返回():
T* release()
{
T* tmp = _ptr;
_ptr = NULL;
return tmp;
}
释放所有权并清空裸指针:
void reset()
{
delete _ptr;
_ptr = NULL;
}
完整代码如下:
template<typename T>
class Munique_ptr
{
public:
explicit Munique_ptr(T* ptr = NULL)//防止隐式构造
{
_ptr = ptr;
}
Munique_ptr(const Munique_ptr&& src)
//&&是右值引用,对于将亡值的引用,必须使用右值引用
{
if (this == &src)
{
return;
}
_ptr = src._ptr;
src._ptr = NULL;//将 将亡值置空
}
Munique_ptr& operator=(Munique_ptr&& src)
{
if (this == &src)//防止自赋值
{
return *this;
}
delete _ptr;//这里还没有调用析构,在赋值之前,需要先delete指针
_ptr = src._ptr;
src._ptr = NULL;
return *this;
}
~Munique_ptr()//unique_ptr的析构函数
{
delete _ptr;
}
T* get()
{
return _ptr;
}
T* release()
{
T* tmp = _ptr;
_ptr = NULL;
return tmp;
}
void reset()
{
delete _ptr;
_ptr = NULL;
}
T* operator->()
{
return _ptr;
}
T& operator*()
{
return *_ptr;
}
operator bool()const//是否还拥有资源
{
return _ptr != NULL;
}
private:
T* _ptr;
};
注意:这是unique_ptr实现将亡值的拷贝构造和赋值运算符重载函数的前提
Munique_ptr<int> fun(Munique_ptr<int>& ptr)
{
cout << *ptr << endl;
return Munique_ptr<int>(new int(10));//new int(10)就是一个将亡值
}
int main()
{
int* p = new int(10);
Munique_ptr<int> u_p1(p);
//Munique_ptr<int> u_p2(p);//报错
u_p1 = fun(u_p1);//将亡值的生存期仅限于这条语句
//Munique_ptr<int>u_p4;
cout << *u_p1 << endl;
u_p1.get();
u_p1.reset();
u_p1.release();
//u_p1.swap();//交换两个智能指针的内部指针
//u_p1.operator bool();
//u_p1.get_deleter();
}