一、概念介绍

  unique_ptr它是一种在异常发生时可帮助避免资源泄露的smart pointer,实现了独占式拥有的概念,意味着它可确保一个对象和其他相应资源在同一时间只被一个pointer拥有,一旦拥有者被销毁或变成空或开始拥有另一个对象,那么先前拥有的那个对象就会被销毁,其任何相应资源亦会被释放。

  Class unique_pt继承自class auto_ptr(由于不安全已被弃用),但它提供了更简明的接口,更不易出错。

1.1 出现的目的性

  为了避免异常时的资源泄露,通常函数会捕获所有的异常,例如:

上图中多个catch时会造成代码臃肿且累赘,使用unique_ptr能很好解决这个问题,改写如下:

1.2 unique_ptr的使用

  unique_ptr有着和寻常指针非常相似的接口,*操作符用来提取指向的对象,如果被指向的对象是class或struct,->操作符还可以用来访问成员,然而由于它是独占式的指针,所以不提供++算术符

 //必须直接初始化,不允许用赋值的语法将一个寻常的指针当作初值
//std::unique_ptr<std::string> = new int;//error
std::unique_ptr<std::string> up(new std::string("nico"));//OK
(*up)[] = 'X'; //替换第一个元素
(*up).append("lai");
std::cout <<(*up).data() << std::endl;
std::cout << up.get()<<std::endl;

  unique_ptr不必一定拥有对象,它也可以是empty,比如是被default构造函数创建出来的:

   也可以使用release放弃拥有权,并转移到另外一个上:

//必须直接初始化,不允许用赋值的语法将一个寻常的指针当作初值
//std::unique_ptr<std::string> = new int;//error
std::unique_ptr<std::string> up(new std::string("nico"));//OK
(*up)[] = 'X'; //替换第一个元素
(*up).append("lai");
std::cout <<(*up).data() << std::endl;
std::cout << up.get()<<std::endl;
auto str = up.release();
//release之后所有权就转移到str了,up就为NULL了
std::cout << str->data();

1.3 转移unique_ptr的拥有权

  unique_ptr提供的语义是“独占式拥有”,然而这个责任必须由我们使用者来确保“不可以使两个unique_ptr以同一个pointer作为初值”,如下:

std::string *sp = new std::string("hello");
std::unique_ptr<std::string> up1(sp);
std::unique_ptr<std::string> up2(sp);//错误,这是个运行期错误,

  27行第一个语句结束后,up1拥有以new创建的对象,第二个语句试图调用copy构造函数,但发生编译期错误,因为up2不可以成为原对象的另一个拥有者,毕竟一次只允许存在一个拥有者,第三个语句则是将拥有权从up1转移到up3,在那之前up3就拥有了先前new建立起来的对象,而up1不再拥有它,一旦up3被销毁,以new创建出来的对象也就被delete,失去拥有权的unique_ptr会变为空,如果要想指派新值,新值必须也是个unique_ptr,不可以是寻常的pointer

std::unique_ptr<std::string> ptr;
//ptr = new std::string; //error
ptr = std::unique_ptr<std::string>(new std::string("hello"));//OK 删除就对象,拥有新对象(delete old object and own new)
ptr = nullptr;//和调用reset差不多,如果有对象的话删除关联的所有对象( deletes the associated,if any)

1.4 转移权unique_ptr两种用途

  拥有权的转移指出了unique_ptr的一种用途:函数可以利用他们将拥有权转移给其他函数

  • (1)、函数是接收端

  如果我们将一个由std::move()建立起来的unique_ptr以rvalue reference身份当作函数实参,那么被调用函数的参数将会取得unique_ptr的拥有权,因此如果该函数不再转移拥有权,对象会在函数结束时被delete:

  • (2)、函数是供应端

  当函数返回一个unique_ptr,其拥有权会转移到调用端内:

  注意:千万不要声明返回类型为rvalue reference,因为那会返回一个dangling pointer(悬空指针)

1.5 unique_ptr被当作成员可避免资源泄露

1.6 unique_ptr对于array的使用

1.7 标准库unique_ptr的默认形式

1.8 自定义deleter

  当我们在unique_ptr结束时不再紧紧是调用delete或delete []时,我们就需要自定义deleter,然而此处的deleter定义方式不同于shared_ptr,你必须具体指明unique_ptr的类型的第二个模板参数,该类型可以时reference to function、function pointer或function object,如果是function object,其函数类型操作符()应该接受一个"指向对象"的pointer

 //自定义deleter
class ClassDeleter
{
public:
void operator()(std::string *p)
{
std::cout << "delete string object" << std::endl;
delete p;
}
}; std::unique_ptr<std::string, ClassDeleter> up(new std::string("hello"));

  如果给入的类型是个函数或lambda,你必须声明deletr的类型为void(*)(T*)或std::function<void(T*)>,要不就使用decltype

1.9 unique_ptr使用举例

 #include <iostream>
#include <string>
#include <memory> // for unique_ptr
#include <dirent.h> // for opendir(), ...
#include <cstring> // for strerror()
#include <cerrno> // for errno
using namespace std; class DirCloser
{
public:
void operator () (DIR* dp) {
if (closedir(dp) != ) {
std::cerr << "OOPS: closedir() failed" << std::endl;
}
}
}; int main()
{
// open current directory:
unique_ptr<DIR,DirCloser> pDir(opendir(".")); // process each directory entry:
struct dirent *dp;
while ((dp = readdir(pDir.get())) != nullptr) {
string filename(dp->d_name);
cout << "process " << filename << endl;
//...
}
}

  上例中使用了标准posix接口:opendir()、readdir()、closedir(),为了确保任何情况下被开启的目录都会被closedir()关闭,我们定义一个unique_ptr,造成只要”指向被开启目录“的那个handle被销毁,DirCloser就会被调用。

1.10 unique_ptr深究

  class unique_ptr提供了一个”带有独占拥有权的smart pointer语义“的概念,一旦某个unique pointer有了独占控制权,你将无法创造出”多个pointer拥有该相应对象“的形势,主要目的是确保在那个pointer寿命结束时,相应对象被删除(或是资源被清理干净),这特别有助于提供异常安全性,相比于shared pointer,这个class关注的是最小量的空间开销和时间开销。

C++2.0新特性(八)——<Smart Pointer(智能指针)之unique_ptr>的更多相关文章

  1. C++2.0新特性(六)——<Smart Pointer(智能指针)之shared_ptr>

    Smart Pointer(智能指针)指的是一类指针,并不是单一某一个指针,它能知道自己被引用的个数以至于在最后一个引用消失时销毁它指向的对象,本文主要介绍C++2.0提供的新东西 一.Smart P ...

  2. C++2.0新特性(七)——<Smart Pointer(智能指针)之weak_ptr>

    一.weak_ptr出现的意义 上一节提到过shared_ptr,它会自动释放“不再需要使用的对象”的相应的资源,但是它不是万能的,在某些时候(比如说循环引用),它会显得力不从心,这就是weak_pt ...

  3. 【C++11新特性】 C++11智能指针之weak_ptr

    如题,我们今天要讲的是C++11引入的三种智能指针中的最后一个:weak_ptr.在学习weak_ptr之前最好对shared_ptr有所了解.如果你还不知道shared_ptr是何物,可以看看我的另 ...

  4. [CareerCup] 13.8 Smart Pointer 智能指针

    13.8 Write a smart pointer class. A smart pointer is a data type, usually implemented with templates ...

  5. C++ smart pointer智能指针

      在C++中,程序员可以直接操作内存,给编程增加了不少的灵活性.但是灵活性是有代价的,程序员必须负责自己负责释放自己申请的内存,否则就会出现内存泄露.智能指针就是为了解决这个问题而存在的.它和其他指 ...

  6. Smart pointer 智能指针小总结

    Smart pointer line 58之后smart pointer里的计数已经是0,所以会真正释放它引用的对象,调用被引用对象的析构函数.如果继续用指针访问,会出现如下图的内存访问异常.所以说如 ...

  7. 【C++11新特性】 C++11智能指针之shared_ptr

    C++中的智能指针首先出现在“准”标准库boost中.随着使用的人越来越多,为了让开发人员更方便.更安全的使用动态内存,C++11也引入了智能指针来管理动态对象.在新标准中,主要提供了shared_p ...

  8. Smart Pointer 智能指针

    P76 参考:http://www.cnblogs.com/lanxuezaipiao/p/4132096.html http://blog.csdn.net/hackbuteer1/article/ ...

  9. [C#]6.0新特性浅谈

    原文:[C#]6.0新特性浅谈 C#6.0出来也有很长一段时间了,虽然新的特性和语法趋于稳定,但是对于大多数程序猿来说,想在工作中用上C#6.0估计还得等上不短的一段时间.所以现在再来聊一聊新版本带来 ...

随机推荐

  1. 从香农熵到手推KL散度

    信息论与信息熵是 AI 或机器学习中非常重要的概念,我们经常需要使用它的关键思想来描述概率分布或者量化概率分布之间的相似性.在本文中,我们从最基本的自信息和信息熵到交叉熵讨论了信息论的基础,再由最大似 ...

  2. Linux系统快速入门方法

    相信看到这篇文章的你一定是想要学习Linux,或者已经在学习Linux的人了,那我们就可以一起探讨一下,学习Linux如何快速入门呢? 首先,希望大家弄清楚自己为什么要学习Linux,有的人是因为兴趣 ...

  3. iOS开发,导入c文件引发的Could not build module 'UIKit'问题

    导致出现异常的原因是是因为工程中添加了某(第三方开源库) 一般情况下出现“Unknown type name”是头文件互相引用出现的,这里可以排除,由于源码使用是c\c++与oc混编, 考虑新的XCo ...

  4. windows nvlddmkm、DRIVER_POWER_STATE_FAILURE 蓝屏问题的解决资料

    背景与现象描述 博主在最近购买了 机械革命 Z2-R (MECHREVO Z2-R Series GK5CP02) 笔记本电脑后,几乎每天均有不下3次的蓝屏,而且机器热时,更甚,达到每天10次以上,简 ...

  5. 【转载】C#中List集合使用LastIndexOf判断元素最后一次出现的索引位置

    在C#的List集合操作中,有时候需要判断元素对象在List集合中第一次出现的索引位置信息,此时需要使用到List集合的IndexOf方法来判断,如果元素存在List集合中,则IndexOf方法返回所 ...

  6. Android 为TV端助力之解决ViewPager嵌套RecyclerView水平滑动问题

    public class MyViewPager extends ViewPager { private RecyclerView recyclerView; public MyViewPager(@ ...

  7. vue-cli 移动端项目如何在手机上调试预览

    这里分享下如何在webpack工具构建下的vue项目,在手机端调试和预览,言归正传. 1.电脑和手机连接到同一个WIFI a.台式电脑和手机同时链接一个路由器,使用同一个wifi: b.笔记本也可以直 ...

  8. php导出数据到csv

    序言 php导出数据到csv是一种很常见的功能,且csv相比于excel文件有其一定的优势,首先csv对数据的行数没有限制,但是excel对数据的行数有一定的限制,因此,csv文件对于导出大量的数据来 ...

  9. 【监控】jvisualvm之jmx远程连接 jar启动应用

    一.Java -jar启动添加如下参数就可以了 -Dcom.sun.management.jmxremote -Djava.rmi.server.hostname=127.0.0.1 -Dcom.su ...

  10. windows10 进入BIOS

    windows10开机进入不了BIOS 原因 上网查了电脑固件所应该有的进入键,什么F1.F2.F12.Delete以及什么要配置Fn+F1...等等方法就是开机进入不了BIOS. 解决办法 最后发现 ...