C++11使用make_shared的优势和劣势
Why Make_shared ?
C++11 中引入了智能指针, 同时还有一个模板函数 std::make_shared
可以返回一个指定类型的 std::shared_ptr
, 那与 std::shared_ptr
的构造函数相比它能给我们带来什么好处呢 ?
优点
效率更高
shared_ptr
需要维护引用计数的信息,
- 强引用, 用来记录当前有多少个存活的 shared_ptrs 正持有该对象. 共享的对象会在最后一个强引用离开的时候销毁( 也可能释放).
- 弱引用, 用来记录当前有多少个正在观察该对象的 weak_ptrs. 当最后一个弱引用离开的时候, 共享的内部信息控制块会被销毁和释放 (共享的对象也会被释放, 如果还没有释放的话).
如果你通过使用原始的 new 表达式分配对象, 然后传递给 shared_ptr (也就是使用 shared_ptr 的构造函数) 的话, shared_ptr 的实现没有办法选择, 而只能单独的分配控制块:
1 |
|
如果选择使用 make_shared
的话, 情况就会变成下面这样:
1 |
|
内存分配的动作, 可以一次性完成. 这减少了内存分配的次数, 而内存分配是代价很高的操作.
关于两种方式的性能测试可以看这里 Experimenting with C++ std::make_shared
异常安全
看看下面的代码:
1 |
|
C++ 是不保证参数求值顺序, 以及内部表达式的求值顺序的, 所以可能的执行顺序如下:
- new Lhs(“foo”))
- new Rhs(“bar”))
- std::shared_ptr
- std::shared_ptr
好了, 现在我们假设在第 2 步的时候, 抛出了一个异常 (比如 out of memory, 总之, Rhs 的构造函数异常了), 那么第一步申请的 Lhs 对象内存泄露了. 这个问题的核心在于, shared_ptr 没有立即获得裸指针.
我们可以用如下方式来修复这个问题.
1 |
|
当然, 推荐的做法是使用 std::make_shared
来代替:
1 |
|
缺点
构造函数是保护或私有时,无法使用 make_shared
make_shared
虽好, 但也存在一些问题, 比如, 当我想要创建的对象没有公有的构造函数时, make_shared
就无法使用了, 当然我们可以使用一些小技巧来解决这个问题, 比如这里 How do I call ::std::make_shared on a class with only protected or private constructors?
对象的内存可能无法及时回收
make_shared
只分配一次内存, 这看起来很好. 减少了内存分配的开销. 问题来了, weak_ptr
会保持控制块(强引用, 以及弱引用的信息)的生命周期, 而因此连带着保持了对象分配的内存, 只有最后一个 weak_ptr
离开作用域时, 内存才会被释放. 原本强引用减为 0 时就可以释放的内存, 现在变为了强引用, 若引用都减为 0 时才能释放, 意外的延迟了内存释放的时间. 这对于内存要求高的场景来说, 是一个需要注意的问题. 关于这个问题可以看这里 make_shared, almost a silver bullet
参考
C++11使用make_shared的优势和劣势的更多相关文章
- Oracle RAC的五大优势及其劣势
Oracle RAC的五大优势及其劣势 不同的集群产品都有自己的特点,RAC的特点包括如下几点: 双机并行.RAC是一种并行模式,并不是传统的主备模式.也就是说,RAC集群的所有成员都可以同时接收客户 ...
- Mono for Android 优势与劣势
原文:Mono for Android 优势与劣势 最近有兴趣了解一下Mono for Andriod,也就是使用.NET平台来开发Andriod程序.Mono for Android API 几乎映 ...
- 17.1.2.1 Advantages and Disadvantages of Statement-Based and Row-Based Replication 基于语句和行的复制的优势和劣势
17.1.2.1 Advantages and Disadvantages of Statement-Based and Row-Based Replication 基于语句和行的复制的优势和劣势 每 ...
- (转)Mono for Android 优势与劣势
最近有兴趣了解一下Mono for Andriod,也就是使用.NET平台来开发Andriod程序.Mono for Android API 几乎映射标准的Andriod API.例如,两边API几乎 ...
- JSP的优势与劣势浅析
本文简单介绍了JSP技术,并对JSP的优势与劣势进行了简单的分析.JSP页面由HTML代码和嵌入其中的Java代码所组成. JSP(JavaServer Pages)是由Sun Microsystem ...
- NanShan即时通讯论——HTML5的优势与劣势
原文:NanShan即时通讯论--HTML5的优势与劣势 NanShan即时通讯 学习html时才是XHTML 1.0,接着是 HTML4.01,再到HTML5,如今HTML5 開始吸引越来越多的人的 ...
- 『Asp.Net 组件』Asp.Net 服务器组件 的开发优势和劣势
在写<Asp.Net 服务器组件系列文档>之前,笔者不才,揣测微软战略用意: 微软利益诉求莫过于 微软产品和技术的市场份额: 因此,微软战略之一莫过于将 所有开发人员 团聚在 微软周围,以 ...
- [转] iOS 动画库 Pop 和 Canvas 各自的优势和劣势是什么?
iOS 动画库 Pop 和 Canvas 各自的优势和劣势是什么? http://www.zhihu.com/question/23654895/answer/25541037 拿 Canvas 来和 ...
- JSP的优势 和劣势 与php的比较
一 jsp的 优势 与劣势 由于JSP页面的内置脚本语言是基于Java编程语言的,而且所有的JSP页面都被编译成为Java Servlet,JSP页面就具有Java技术的所有好处,包括健壮的存储管理和 ...
随机推荐
- Microsoft Onenote shortcuts / Onenote快捷键大全
Onenote跟Libreoffice ,有道笔记比起来一个快捷键特别不太好用,就是Ctrl + Shift +v 并不会提供一个选择粘贴模式选项. 而在Onenote 中 Ctrl + Shift ...
- java 懒汉式、饿汉式单例模式 不含多线程的情况
//饿汉式 提前生成了单例对象 class Singleton{ private static final Singleton instance=new Singleton(); private Si ...
- Spring源码窥探之:ImportSelector
1. 编写实现ImportSelector的类 /** * @author 70KG * @Title: SelectImportBean * @Description: * @date 2018/7 ...
- HDFS节点及原理
HDFS节点角色: (1)namenode:1.用来存储HDFS的元数据信息,这里的元数据信息指的是文件系统的命名空间.启动时,将这些信息加载到namenode内存. 2.元数据信息也会在磁盘上保存成 ...
- CF19D Points 平衡树
题意:支持插入/删除点 $(x,y)$,查询一个点右上方横坐标与之最接近的点坐标. 我们可以对于每一个操作过的横坐标都开一个 $set$,然后再开一个平衡树,维护每个横坐标上最大的纵坐标. 然后查询点 ...
- cgp的辣鸡比赛题解
目录 cgp的gcd 题目链接 思路 代码 cgp调戏妹子 题目链接 思路 代码 cgp的序列 题目链接 思路 代码 cgp的背包 题目链接 思路 代码 cgp的gcd 题目链接 传送门 思路 首先看 ...
- Processing 2.1.1 无法使用video和movie问题解决方案
升级到2.1.1后,尝试着运行了一下sample中的video和movie,结果都报错,上网搜了一下,找到解决方法. 1. 首先来看movie的错误,如下: JNA: Callback org.gst ...
- AtCoder Grand Contest 015题解
传送门 \(A\) 找到能达到的最大的和最小的,那么中间任意一个都可以被表示出来 typedef long long ll; int n,a,b;ll res; int main(){ scanf(& ...
- cometoj---contest#3 棋盘
棋盘:(状压dp) 传送门:https://www.cometoj.com/contest/38/problem/B?problem_id=1535 题目描述 小猫有一个 2×N 的棋盘,每一个格子放 ...
- SqrtTree学习笔记
散步的时候yy区间最值的不同分块做法,发现单点修改\(O(\sqrt{n})\)查询\(O(1)\)的做法不是很会? 于是yy了一个奇怪做法,写出来看看. 考虑查询的时候两端的散点可以用前后缀最值查出 ...