<Effective Modern C++>Item 18: Use std::unique_ptr for exclusive-ownership resource management.
来源:互联网 发布:卖esse爱喜烟的淘宝店 编辑:程序博客网 时间:2024/05/22 10:56
特别提这一章是因为自己习惯于使用
shared_ptr
,而一直忽略unique_ptr
的使用,甚至对exclusive-ownership
的对象我也是一律采用shared_ptr
的方案,而丝毫没有考虑unique_ptr
的感受…所以必须总结一番unique_ptr
的特性。
首先先简单回顾一番智能指针的发展历程…
在C++98之前,标准库中已经有了std::auto_ptr
这样的智能指针,这可以看作是C++对RAII
思想的一种尝试,所以auto_ptr
的成熟度是不合格的。C++11
带来了三种现代指针:shared_ptr / unique_ptr / weak_ptr
,其中shared_ptr
与weak_ptr
是配合使用的,而unique_ptr
则完全替代了auto_ptr
。
所以除非是不得已要维护C++98之前的代码,那么请弃用auto_ptr
。
好的下面是我们今天的主角——unique_ptr
。
不仅unique_ptr
的行为接近原生指针,它的内存占用也可以认为是和原生指针一样的(使用默认的deleter
),可以说是非常轻量级了,因此大多场景下也应该是我们的优先考虑对象。
一个unique_ptr
会独占它所指向的实例,但更需要注意的是——unique_ptr
是moveable but not copyable
的。uncopyable
很好理解,毕竟和unique
对应上了,其拷贝构造函数和赋值操作符都通过=delete
禁用了。但是moveable
一开始却十分困惑我。然而存在及合理——一方面,我猜测是为了优化性能,其次是可以将源指针的管理权限通过move
转移到目标指针,注意是转!移!而不是赋值/复制,但更重要的,moveable
的特性为unique_ptr
存入容器和作为函数返回值 提供了可能。
重点说作为函数返回值。 unique_ptr
作为函数返回值的一个典型应用就是工厂模式
,实现如下:
template<class T, typename... Types>unique_ptr<T> getInstance(Types&&... Args){ return (unique_ptr<T>(new T(std::forward<Types>(Args)...))); }/* 既然用了C++14那么也可以更彻底一点template<class T, typename... Types>auto getInstance(Types&&... Args){ return (unique_ptr<T>(new T(std::forward<Types>(Args)...))); }*///通过如下调用使用auto new_instance=getInstance(params);
经过测试,在return
语句中构造unique_ptr
对象确实不会调用拷贝构造函数,查阅相关资料后发现:
当函数返回一个对象时,理论上会产生临时变量,那必然是会导致新对象的构造和旧对象的析构,这对效率是有影响的。C++编译针对这种情况允许进行优化,哪怕是构造函数有副作用,这叫做返回值优化(RVO),返回有名字的对象叫做具名返回值优化(NRVO).
酷的不行…
unique_ptr
和shared_ptr
一样,有一个默认的删除器(直接使用delete
删除对应指针),但是用户也可以根据所管理的对象构成设计自己的删除器,就像下面这样:
// C++11/14风格 + lambda表达式auto delInstance = [](SomeClass* pInstance){makeLogEntry(pInstance);// sth else.delete pInstance;};//在构造unique_ptr时传入删除器std::unique_ptr<SomeClass,decltype(delInstance)> pIns(nullptr,delInstance);
注:指定模板类型时使用decltype
推导delInstance
的类型,在构造实例时传入具体的delInstance
方法作为删除器,书中更建议使用lambda
来设计删除器,积极拥抱新标准。
(此时unique_ptr
的大小可就和原生指针不一样了,具体大小取决于删除器这个function object
是如何工作的,不合理的删除器设计往往会导致unique_ptr
的大小膨胀)
unique_ptr
是有两种形式的——单独的实体(std::unique_ptr<T>
)和数组(std::unique_ptr<T[]>
),具体如何使用取决于使用者,但要注意前者没有重载[]
,而后者没有重载*
/ ->
。
总之,对于exclusive-ownership
的对象,应该尽量使用unique_ptr
,这才是其实际意义所在,并且unique_ptr
与shared_ptr
之前的转换也十分方便,甚至可以用直接前面的getInstance
函数构造一个shared_ptr
对象。
- <Effective Modern C++>Item 18: Use std::unique_ptr for exclusive-ownership resource management.
- Item18 Use std::unique_ptr for exclusive-ownership resource management
- Effective Modern C++ 条款18 用std::unique_ptr管理独占所有权的资源
- <Effective Modern C++>Item 15: Use constexpr whenever possible.[constexpr 表达式]
- unique_ptr, effective modern c++笔记
- 《Effective Modern C++》Item 1总结
- 《Effective Modern C++》Item 2总结
- Effective Modern C++》Item 3总结
- Effective Modern C++: Item 3 ->弄清decltype
- Effective Objective-C 2.0: Item 35: Use Zombies to Help Debug Memory-Management Problems
- Effective Modern C++:Item 2 ->弄清auto类型推断
- Effective Modern C++: Item 4 -> 知道如何查看推断类型
- Effective Modern C++: Item 7 -> 创建对象时分清()和{}
- Effective Modern C++: Item 12 -> 声明覆盖函数override
- Effective Modern C++: Item 13 -> 优先选择const_iterators而不是iterators
- Effective Modern C++ Item Lists
- Effective Modern C++ Item 1
- Effective Modern C++ Item 2
- 深入理解计算机系统读书笔记
- 关于入职第二天
- 怎么用IDEA上传本地项目到码云/Github?
- 数据库学习纪要(二十三):MySQL-3-SELECT
- Android 代码设置TextView、Button等控件圆角边框背景颜色
- <Effective Modern C++>Item 18: Use std::unique_ptr for exclusive-ownership resource management.
- 对计算机科学中的算法学习总结(32个算法)
- python零碎知识(8)--文件和流
- 数字证书中主题(Subject)中字段的含义
- 简单入门小程序 01
- CXF的异常处理
- EventBus用法全解析
- 电商笔记-07(solr全文检索lunix中的搭建与商品的上架)
- SonarQube 之 gitlab-plugin 配合 gitlab-ci 完成每次 commit 代码检测