C++(标准库):06---智能指针之unique_ptr

一、unique_ptr类

  • 头文件:#include<memory>
  • 智能指针,是一个模板。创建智能指针时,必须提供指针所指的类型

与shared_ptr的不同之处:

  • shared_ptr所指向的对象可以有多个其他shared_ptr智能指针
  • 而unique_ptr所指向的对象只能有一个unique_ptr指针,也就是自己。当unique_ptr被销毁时,它所指向的对象也被销毁

二、unique_ptr类的初始化

  • unique_ptr指针需要绑定到一个new返回的指针上,并且不能直接将new的结果用赋值运算符“=”赋值给unique_ptr
unique_ptr<double> p1;//正确
unique_ptr<int> p2(new int(42));//正确
unique_ptr<int> p3 = new int(42);//错误

三、unique_ptr之间不存在拷贝与赋值

  • 原因:因为unique_ptr所指向的对象只能有一个unique_ptr指针,也就是一个引用计数。因此unique_ptr不支持普通的拷贝和赋值操作
unique_ptr<string> p1(new string("HelloWorld"));

unique_ptr<string> p2(p1);//是错误

unique_ptr<string> p3;
p3 = p1;//错误

特殊情况:

  • 虽然两个unique_ptr不可以同时指向同一个内存对象,但是可以将一个即将销毁的unqie_ptr指针拷贝或赋值给另一个unqie_ptr
  • 函数的参数传递和返回值就是一个很好的例子
//因为在函数内部的unique_ptr指针随着作用域的结束会自动销毁,因此可以将其作为返回值,然后将内存传递给另一个unique_ptr指针管理
unique_ptr<int> clone(int p)
{
    return unique_ptr<int>(new int(p));
}

/*unique_ptr<int> clone(int p)
{
    unique_ptr<int> ret(new int(p));
    return ret;
}*/
int main()
{
    unique_ptr<int> p = clone(10);
    cout <<*p << endl; //打印10
    return 0;
}

四、release、reset函数的使用

  • 虽然unique_ptr之间不能拷贝与赋值。但是可以使用release和reset函数来将指针的所有权从一个(非const)unique_ptr转移给另一个unique

release函数

  • 将当前的unique_ptr指针所指的内存置为空,并且对这块内存的所有权消失
  • 返回值:返回当前unique_ptr所指的内存
unique_ptr<string> p1(new string("Hello"));

unique_ptr<string> p2(p1.release());//p1将自己所指的内存空间置空,并且返回该内存空间。之后对该内存空间的操作权消失,从而p2得到该内存的权限

注意事项:

  • 因为release函数会使unque_ptr指针与内存之间的关系。所以unique_ptr调用release函数之后必须将返回值传递给另一个unqiue_ptr,否则就会内存泄露
unique_ptr<string> p1(new string("Hello"));
p1.release();//错误,虽然p1断开了与内存的关系,但是没有另一个unqieu_ptr来接手这块内存,造成内存泄漏

/*
改正:
unique_ptr<string> p2(p1.release()); //将p1的原来内存交给另一个unique_ptr管理
*/

reset函数

  • 用来重置当前unqie_ptr指针。
  • 重置之后接手另一块内存或者一直处于空状态
unique_ptr<string> p1(new string("Hello"));
p1.reset();//将p1置空,不指向内存对象
unique_ptr<string> p1(new string("Hello"));
p1.reset(nullptr);//同上
unique_ptr<string> p1(new string("Hello"));
unique_ptr<string> p2(new string("World"));

p1.reset(p2.release());//p2置空之后,然后p1也置空,然后p1来接手p2所指向的内存

五、重置unique_ptr类删除器

语法格式:

  • 与shared_ptr重载删除器不同,unique_ptr重载删除器会影响到unique_ptr类型以及如何构造(或reset)该类型的对象
  • 我们必须在unique_ptr指向类型之后提供删除器
//p指向一个类型为objT的对象,并使用一个类型为delT的对象释放objT对象
//它会调用一个名为fcn的delT类型对象

unique_ptr<objT,delT> p(new objT,fcn);

演示案例:

void f(destination &d)
{
    connection c=connec(&d);
    unique_ptr<connection,decltype(end_connection)*> p(&c,end_connection);

    ...//使用这个连接
     //当f函数退出或者异常退出,p都会调用end_connection函数
}

六、unique_ptr与动态数组的使用

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

董哥的黑板报

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值