C++系列学习

C++系列学习,第1张

[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
    }
    
    #还可以返回一个局部对象的拷贝
    unique_ptr<int> clone(int p)
    {
    	unique_ptr<int> ret(new int(p));
    	//……
    	return ret;
    }
    
4. unique_ptr *** 作
	```
	unique_ptr u1;		// 空unique_ptr,可以指向类型为T的对象。u1会使用delete来释放它的指针。
	unique_ptr u2;	// u2会使用一个类型为D的可调用对象来释放它的指针
	unique_ptr 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主要的使用场景

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/788929.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-05
下一篇 2022-05-05

发表评论

登录后才能评论

评论列表(0条)

保存