c++11:智能指针之unique_ptr
2017-09-23 16:12
288 查看
unique_ptr 不共享它的指针。它无法复制到其他 unique_ptr,无法通过值传递到函数,也无法用于需要副本的任何标准模板库 (STL) 算法。只能移动unique_ptr。这意味着,内存资源所有权将转移到另一 unique_ptr,并且原始 unique_ptr 不再拥有此资源。我们建议你将对象限制为由一个所有者所有,因为多个所有权会使程序逻辑变得复杂。因此,当需要智能指针用于纯 C++ 对象时,可使用 unique_ptr,而当构造 unique_ptr 时,可使用make_unique Helper 函数。std::unique_ptr实现了独享所有权的语义。一个非空的std::unique_ptr总是拥有它所指向的资源。转移一个std::unique_ptr将会把所有权也从源指针转移给目标指针(源指针被置空)。拷贝一个std::unique_ptr将不被允许,因为如果你拷贝一个std::unique_ptr,那么拷贝结束后,这两个std::unique_ptr都会指向相同的资源,它们都认为自己拥有这块资源(所以都会企图释放)。因此std::unique_ptr是一个仅能移动(move_only)的类型。当指针析构时,它所拥有的资源也被销毁。默认情况下,资源的析构是伴随着调用std::unique_ptr内部的原始指针的delete操作的。下图演示了两个 unique_ptr 实例之间的所有权转换。
程序试图将一个 unique_ptr 赋值给另一个时,如果源 unique_ptr 是个临时右值,编译器允许这么做;如果源 unique_ptr 将存在一段时间,编译器将禁止这么做,比如:
这是我们传统的写法:当我们动态申请内存后,有可能我们接下来的代码由于抛出异常或者提前退出(if语句)而没有执行delete操作。解决的方法是使用unique_ptr来管理动态内存,只要unique_ptr指针创建成功,其析构函数都会被调用。确保动态资源被释放。
1、如何创建unique_ptr
unique_ptr不像shared_ptr一样拥有标准库函数make_shared来创建一个shared_ptr实例。要想创建一个unique_ptr,我们需要将一个new 操作符返回的指针传递给unique_ptr的构造函数。示例:int main() { // 创建一个unique_ptr实例 unique_ptr<int> pInt(new int(5)); cout << *pInt; }
2、无法进行复制构造和赋值操作
unique_ptr没有copy构造函数,不支持普通的拷贝和赋值操作。int main() { // 创建一个unique_ptr实例 unique_ptr<int> pInt(new int(5)); unique_ptr<int> pInt2(pInt); // 报错 unique_ptr<int> pInt3 = pInt; // 报错 }
3、可以进行移动构造和移动赋值操作
unique_ptr虽然没有支持普通的拷贝和赋值操作,但却提供了一种移动机制来将指针的所有权从一个unique_ptr转移给另一个unique_ptr。如果需要转移所有权,可以使用std::move()函数。示例:int main() { unique_ptr<int> pInt(new int(5)); unique_ptr<int> pInt2 = std::move(pInt); // 转移所有权 //cout << *pInt << endl; // 出错,pInt为空 cout << *pInt2 << endl; unique_ptr<int> pInt3(std::move(pInt2)); }
程序试图将一个 unique_ptr 赋值给另一个时,如果源 unique_ptr 是个临时右值,编译器允许这么做;如果源 unique_ptr 将存在一段时间,编译器将禁止这么做,比如:
unique_ptr<string> pu1(new string ("hello world")); unique_ptr<string> pu2; pu2 = pu1; // #1 not allowed unique_ptr<string> pu3; pu3 = unique_ptr<string>(new string ("You")); // #2 allowed其中#1留下悬挂的unique_ptr(pu1),这可能导致危害。而#2不会留下悬挂的unique_ptr,因为它调用 unique_ptr 的构造函数,该构造函数创建的临时对象在其所有权让给 pu3 后就会被销毁。
4、可以返回unique_ptr
unique_ptr不支持拷贝操作,但却有一个例外:可以从函数中返回一个unique_ptr。示例:unique_ptr<int> clone(int p) { unique_ptr<int> pInt(new int(p)); return pInt; // 返回unique_ptr } int main() { int p = 5; unique_ptr<int> ret = clone(p); cout << *ret << endl; }
unique_ptr使用场景
1、为动态申请的资源提供异常安全保证
我们先来看看下面这一段代码:void Func() { int *p = new int(5); // ...(可能会抛出异常) delete p; }
这是我们传统的写法:当我们动态申请内存后,有可能我们接下来的代码由于抛出异常或者提前退出(if语句)而没有执行delete操作。解决的方法是使用unique_ptr来管理动态内存,只要unique_ptr指针创建成功,其析构函数都会被调用。确保动态资源被释放。
void Func() { unique_ptr<int> p(new int(5)); // ...(可能会抛出异常) }
2、返回函数内动态申请资源的所有权
unique_ptr<int> Func(int p) { unique_ptr<int> pInt(new int(p)); return pInt; // 返回unique_ptr } int main() { int p = 5; unique_ptr<int> ret = Func(p); cout << *ret << endl; // 函数结束后,自动释放资源 }
3、在容器中保存指针
int main() { vector<unique_ptr<int>> vec; unique_ptr<int> p(new int(5)); vec.push_back(std::move(p)); // 使用移动语义 }
4、管理动态数组
标准库提供了一个可以管理动态数组的unique_ptr版本。int main() { unique_ptr<int[]> p(new int[5] {1, 2, 3, 4, 5}); p[0] = 0; // 重载了operator[] }
5、作为auto_ptr的替代品
相关文章推荐
- c++11之unique_ptr智能指针使用
- 【C++11新特性】 C++11智能指针之unique_ptr
- C++11 智能指针——unique_ptr
- C++11新特性之智能指针(shared_ptr/unique_ptr/weak_ptr)
- C++11智能指针之unique_ptr
- C++11智能指针之unique_ptr
- (转载)【C++11新特性】 C++11智能指针之unique_ptr
- C++11 智能指针unique_ptr使用 -- 以排序二叉树为例
- C++11智能指针之unique_ptr
- 【C++11新特性】 C++11智能指针之unique_ptr
- C++11智能指针之unique_ptr
- C++11智能指针之std::unique_ptr
- C++11引入智能指针std::unique_ptr
- C++11教程1 智能指针——unique_ptr
- C++11 智能指针unique_ptr
- 【C++11新特性】 C++11智能指针之unique_ptr
- C++11新特性之智能指针(shared_ptr/unique_ptr/weak_ptr)
- C++11新特性之智能指针(shared_ptr/unique_ptr/weak_ptr)
- C++11 unique_ptr独占的智能指针
- c++11 智能指针 unique_ptr、shared_ptr与weak_ptr