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实例之间的所有权转换:
-
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); //移动构造,转移所有权
-
不能拷贝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; }
```
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使用场景
-
**为动态申请的资源提供异常安全保证:**当动态申请内存后,可能会由于抛出异常或提前退出而没有指向delete *** 作,解决办法是使用unique_ptr来管理动态内存,只有unique_ptr指针创建成功,其析构函数都会被调用,确保动态资源被释放。
-
返回函数内动态申请资源的所有权
-
在容器中保存指针:
std::vector<unique_ptr<int>> vec; unique_ptr<int> p(new int(5)); vec.push_back(std::move(p)); //使用移动语义
-
管理动态数组
-
作为auto_ptr的替代
- unique_ptr独占对象,只有移动语义
- unique_ptr可以不占有对象,即为空。可以通过nullptr或reset()释放管理对象
- 标准库早期版本定义了auto_ptr,它具有unique_ptr的部分特征,但不是全部。例如不能在容器中保存auto_ptr,不能从函数中返回auto_ptr等,这也是unique_ptr主要的使用场景
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)