C++系列学习

[C++11] std::unique_ptr详解

std::unique_ptr是C++11引入的智能指针。C++11引入了move语义,可以转移对象的所有权。

1. unique_ptr介绍

  • unique_ptr不共享其指针。它不能复制到另一个unique_ptr,无法通过值传递到函数,也无法用于需要副本的任何标准模板库算法。只能移动unique_ptr。这意味着,内存资源所有权将转移到另一unique_ptr,并且原始unique_ptr不再拥有此资源。当需要智能指针拥有纯C++对象时,可使用unique_ptr,而当构造unique_ptr时,可使用make_unique函数。
  • 下图演示了两个unique_ptr实例之间的所有权转换:
    在这里插入图片描述

2. 创建unique_ptr

  • unique_ptr与shared_ptr不同,没有类似make_shared的标准库函数返回一个unique_ptr。要创建一个unique_ptr,需要将其绑定到一个new返回的指针上。

  • std::make_unique是C++14才有的特性

    unique_ptr<double> p1; //可以指向一个double的unique_ptr
    unique_ptr<int> p2(new int(42));	//p2指向一个值为42的int
    
  • 由于一个unique_ptr拥有它指向的对象,因此unique_ptr不支持普通的拷贝或赋值操作

    unique_ptr<string> p1(new string("hello");
    unique_ptr<string> p2(p1);	//错误:unique_ptr不支持拷贝
    unique_ptr<string> p3;
    p3 = p1;					//错误:unique_ptr不支持赋值
    
  • unique_ptr可以进行移动构造和移动赋值操作。如果需要转移所有权,可以使用std::move()函数

    unique_ptr<int> p1(new int(5));
    unique_ptr<int> p2 = std::move(p1);	//转移所有权
    unique_ptr<int> p3(std::move(p2);	//移动构造,转移所有权
    

3. 传递unique_ptr和返回unique_ptr

  • 不能拷贝unique_ptr的规则有一个例外:可以拷贝或赋值一个将要被销毁的unique_ptr。此时,执行一种特殊的拷贝(移动拷贝)

    #最常见的例子是从函数返回一个unique_ptr。
    unique_ptr<int> clone(int p)
    {
    	return unique_ptr<int>(new int(p));	//正确:从int*创建一个unique_ptr<int>
    }
    
    #还可以返回一个局部对象的拷贝
    unique_ptr<int> clone(int p)
    {
    	unique_ptr<int> ret(new int(p));
    	//……
    	return ret;
    }
    

4. unique_ptr操作

	```
	unique_ptr<T> u1;		// 空unique_ptr,可以指向类型为T的对象。u1会使用delete来释放它的指针。
	unique_ptr<T, D> u2;	// u2会使用一个类型为D的可调用对象来释放它的指针
	unique_ptr<T, D> u(d);	// 空unique_ptr,指向类型为T的对象,用类型为D的对象d代替delete;
	u = nulptr;				// 释放u指向的对象,将u置为空
	u.release();			// u放弃对指针的控制权,返回指针,并将u置为空
	u.reset();				// 释放u指向的对象
	u.reset(q);				// 如果提供了内置指针q,令u指向这个对象;否则将u置为空
	u.reset(nullptr);
	```

5. unique_ptr使用场景

  1. **为动态申请的资源提供异常安全保证:**当动态申请内存后,可能会由于抛出异常或提前退出而没有指向delete操作,解决办法是使用unique_ptr来管理动态内存,只有unique_ptr指针创建成功,其析构函数都会被调用,确保动态资源被释放。

  2. 返回函数内动态申请资源的所有权

  3. 在容器中保存指针:

    std::vector<unique_ptr<int>> vec;
    unique_ptr<int> p(new int(5));
    vec.push_back(std::move(p));		//使用移动语义
    
  4. 管理动态数组

  5. 作为auto_ptr的替代

6. 总结

  1. unique_ptr独占对象,只有移动语义
  2. unique_ptr可以不占有对象,即为空。可以通过nullptr或reset()释放管理对象
  3. 标准库早期版本定义了auto_ptr,它具有unique_ptr的部分特征,但不是全部。例如不能在容器中保存auto_ptr,不能从函数中返回auto_ptr等,这也是unique_ptr主要的使用场景
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值