C++2.0新特性(八)——<Smart Pointer(智能指针)之unique_ptr>
一、概念介绍
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>的更多相关文章
- C++2.0新特性(六)——<Smart Pointer(智能指针)之shared_ptr>
Smart Pointer(智能指针)指的是一类指针,并不是单一某一个指针,它能知道自己被引用的个数以至于在最后一个引用消失时销毁它指向的对象,本文主要介绍C++2.0提供的新东西 一.Smart P ...
- C++2.0新特性(七)——<Smart Pointer(智能指针)之weak_ptr>
一.weak_ptr出现的意义 上一节提到过shared_ptr,它会自动释放“不再需要使用的对象”的相应的资源,但是它不是万能的,在某些时候(比如说循环引用),它会显得力不从心,这就是weak_pt ...
- 【C++11新特性】 C++11智能指针之weak_ptr
如题,我们今天要讲的是C++11引入的三种智能指针中的最后一个:weak_ptr.在学习weak_ptr之前最好对shared_ptr有所了解.如果你还不知道shared_ptr是何物,可以看看我的另 ...
- [CareerCup] 13.8 Smart Pointer 智能指针
13.8 Write a smart pointer class. A smart pointer is a data type, usually implemented with templates ...
- C++ smart pointer智能指针
在C++中,程序员可以直接操作内存,给编程增加了不少的灵活性.但是灵活性是有代价的,程序员必须负责自己负责释放自己申请的内存,否则就会出现内存泄露.智能指针就是为了解决这个问题而存在的.它和其他指 ...
- Smart pointer 智能指针小总结
Smart pointer line 58之后smart pointer里的计数已经是0,所以会真正释放它引用的对象,调用被引用对象的析构函数.如果继续用指针访问,会出现如下图的内存访问异常.所以说如 ...
- 【C++11新特性】 C++11智能指针之shared_ptr
C++中的智能指针首先出现在“准”标准库boost中.随着使用的人越来越多,为了让开发人员更方便.更安全的使用动态内存,C++11也引入了智能指针来管理动态对象.在新标准中,主要提供了shared_p ...
- Smart Pointer 智能指针
P76 参考:http://www.cnblogs.com/lanxuezaipiao/p/4132096.html http://blog.csdn.net/hackbuteer1/article/ ...
- [C#]6.0新特性浅谈
原文:[C#]6.0新特性浅谈 C#6.0出来也有很长一段时间了,虽然新的特性和语法趋于稳定,但是对于大多数程序猿来说,想在工作中用上C#6.0估计还得等上不短的一段时间.所以现在再来聊一聊新版本带来 ...
随机推荐
- 所有子模块都要执行的checkstyle检查
<!-- 所有子模块都要执行的checkstyle检查 --> <plugin> <groupId>org.apache.maven.plugins</gro ...
- react学习记录(一)
一.React是什么 声明式写法(强调结果,命令式编程强调过程) 组件化 一次学习,随处编写(多种应用场景,web程序,原生手机应用,系统应用,命令行工具) 二.为什么学习react 大公司加持-fa ...
- Spring框架的核心概念是什么?需要掌握的知识点都有哪些?
Spring其主要精髓 就是IOC和AOP.掌握好了这两点对于理解Spring的思想颇有意义. IOC(英文 Inversion of Control)就是控制反转的意思.就是把新建对象(new Ob ...
- ORACLE ASMLIB
ORACLE ASMLIB This blog post is more of a note for myself on configuring ASMLib. ASMLib is an opti ...
- idea之将Maven的jar包安装到本地仓库
1.问题概要 很多时候,我们需要应用第三方的jar包,但是这个jar包,在maven远程仓库里面没有, 比如我们要使用京东的sdk,但这个sdk在maven的远程仓库中没有,于是我们需要将这个jar包 ...
- JMeter java.net.BindException: Address already in use: connect
原文:https://blog.csdn.net/macwhirr123/article/details/77199057 出现原因:TCP/IP连接数不够或TIME_WAIT中存在很多链接,导致吞吐 ...
- 【转】vsftpd用户登入不进去问题
实在是登陆不上... 我已经加了一个新的用户UID和GID都设置到1000以后 /etc/vsftpd.conf也加了local_enable=yes 以standalone模式运行. 重启服务器后, ...
- 【Maven错误】 Non-resolvable parent POM for ...... Return code is: 500 , ReasonPhrase:Internal Server Error. and 'parent.relativePath' points at no local POM @ line 14, column 11
一.异常信息 [INFO] Scanning for projects... Downloading: http://www.myhost.com/maven/jdk18/org/springfram ...
- Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-C. Magic Grid-构造
Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-C. Magic Grid-构造 [Problem Descripti ...
- 编程小白入门分享一:git的最基本使用
git简介 引用了网上的一张图,这张图清晰表达git的架构.workspace是工作区,可以用编辑器直接编辑其中的文件:Index/Stage是暂存区,编辑后的文件可以添加到(add)暂存区:Repo ...