探究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
2
auto p = new widget();
shared_ptr sp1{ p }, sp2{ sp1 };

 

如果选择使用 make_shared 的话, 情况就会变成下面这样:

 

1
auto sp1 = make_shared(), sp2{ sp1 };

 

内存分配的动作, 可以一次性完成. 这减少了内存分配的次数, 而内存分配是代价很高的操作.

关于两种方式的性能测试可以看这里 Experimenting with C++ std::make_shared

异常安全

看看下面的代码:

 

1
2
3
4
void F(const std::shared_ptr<Lhs>& lhs, const std::shared_ptr<Rhs>& rhs) { /* ... */ }F(std::shared_ptr<Lhs>(new Lhs("foo")),std::shared_ptr<Rhs>(new Rhs("bar")));

C++ 是不保证参数求值顺序, 以及内部表达式的求值顺序的, 所以可能的执行顺序如下:

  1. new Lhs(“foo”))
  2. new Rhs(“bar”))
  3. std::shared_ptr
  4. std::shared_ptr

好了, 现在我们假设在第 2 步的时候, 抛出了一个异常 (比如 out of memory, 总之, Rhs 的构造函数异常了), 那么第一步申请的 Lhs 对象内存泄露了. 这个问题的核心在于, shared_ptr 没有立即获得裸指针.

我们可以用如下方式来修复这个问题.

 

1
2
3
auto lhs = std::shared_ptr<Lhs>(new Lhs("foo"));
auto rhs = std::shared_ptr<Rhs>(new Rhs("bar"));
F(lhs, rhs);

当然, 推荐的做法是使用 std::make_shared 来代替:

 

1
F(std::make_shared<Lhs>("foo"), std::make_shared<Rhs>("bar"));

缺点

构造函数是保护或私有时,无法使用 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

参考

  • GotW #89 Solution: Smart Pointers
  • cppreference.com – std::make_shared

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/548151.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

asp.net实现ftp上传代码(解决大文件上传问题)

原来使用asp.net上传控件上传 那个虽然简单但是页面不是很友好 然后就用了uploadify上传控件 这个控件虽然界面友好 但是大文件还是不能上传 而且在不同的浏览器会出现session丢失问题 所以我到了个ftp上传的方法 以下是具体代码 View Code?11 using System; 2 using System…

tolua++

一.tolua简介tolua是一种第三方的软件包,可以为Lua提供面向对象的特性,这样我们就可以使用Lua来编写使用C语言库的脚本文件.二.tolua的编译. tolua的主页在http://www.codenix.com/~tolua/,目前的最新版本是1.0.7,为了使用tolua,我们需要三个文件: 1.bin/tolua[.exe…

IE6PNG8PNG24test

2019独角兽企业重金招聘Python工程师标准>>> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http://www.w3.org/1999/xhtml"&…

开发 Windows 8 Bing地图应用(2)

下面是对使用JavaScript的Bing Maps Trip Optimizer示例的介绍&#xff0c;讲述应用的JavaScript部分组织形式&#xff0c;本地的上下文和网络上下文之间的通信。 WinRT需要访问网络的代码&#xff0c;下面是一些需要访问网络的活动示例。 q 加载一个外部JavaScript文件&#x…

再谈C#委托与事件

转自&#xff1a;http://ruizhinet.blog.163.com/blog/static/9921382820092801032681/ 之前写过一篇关于C#委托与事件的文章&#xff08;见《C#委托和事件例析》&#xff09;&#xff0c;不过还是收到一些网友的提问。所以&#xff0c;今天再换另一个角度来详解一下这个问题。…

2021年软考中级过关

虽然分数不高&#xff0c;但足以证明&#xff0c;付出总有回报。 个人感觉在软考中级里面来讲&#xff0c;软件设计师历年的通过率在30%左右&#xff0c;根据通过率可以判断考试难度不是很大。 软件设计师考试属于软考中级资格&#xff0c;软件设计师比软考高级考试难度要小&…

软件工程文档

软件工程文档 文档是软件开发使用和维护当中必备的资料&#xff0c;文档主要是管理人员、开发人员、操作人员、用户人员之间进行协商沟通的桥梁。 1.可行性分析文档 主要是说明软件在经济上&#xff0c;技术上和市场情景等方面的可行性。根据这个文档&#xff0c;公司判断软件能…

fatal error C1010: unexpected end of file while...

为什么80%的码农都做不了架构师&#xff1f;>>> 在编译VC6.0是,出现fatal error C1010: unexpected end of file while looking for precompiled header directive 的错误. 解决方法&#xff1a; 1、如果发生错误的文件是由其他的C代码文件添加进入当前工程而引…

OpenGL 人物走动源码

2019独角兽企业重金招聘Python工程师标准>>> OpenGL 人物走动源码&#xff0c;记得前两天发了一个OpenGL的立方体程序&#xff0c;这个比那个厉害&#xff0c;这个是一个可以走动的小怪兽&#xff01; 转载:http://www.adobex.com/android/source/details/00000064.…

在Hyper-v中创建并安装虚拟机

1.1.1 创建并安装虚拟机 创建并安装虚拟机系统的步骤&#xff1a; 1. 点击“开始”“程序”“管理工具”“Hyper-V 管理器”。 2. 如图点击“新建”“虚拟机”。 3. 在出现的开始之前对话框&#xff0c;点击“下一步”。 4. 在指定名称和位置对话框&#xff0c;输入名称&#x…

ubuntu部署tomcat

安装版本&#xff1a;apache-tomcat-7.0.29.tar.gz&#xff08;官方网址&#xff1a;Apache Tomcat&#xff09; 安装步骤&#xff1a; 1、下载 Tomcat 下载 apache-tomcat-7.0.29.tar.gz&#xff08;官方网址&#xff09; 2、解压 Tomcat 解压 apache-tomcat-7.0.29.tar.gz ta…

android 底部菜单

2019独角兽企业重金招聘Python工程师标准>>> 新浪微薄上的一个底部菜单的实现,有兴趣的 可以看一下转载:http://www.adobex.com/android/source/details/00000118.htm 转载于:https://my.oschina.net/androidcode/blog/103835

PullToRefresh

2019独角兽企业重金招聘Python工程师标准>>> 实现下拉刷新列表内容的效果。 Code4App编译测试&#xff0c;测试环境&#xff1a;Xcode 4.3, iOS 5.0。 转载:http://www.adobex.com/ios/source/details/00000062.htm 转载于:https://my.oschina.net/u/868244/blog/10…

LYNC文件传输功能开关

LYNC如何关闭和开启文件传输功能&#xff1f;大家都知道有文件筛选的控制&#xff0c;在POWERSHELL也没有看到关闭文件传输的命令。其实这个功能在控制台上一个不显眼的位置&#xff0c;见下图&#xff1a; 此处的勾用来控制客户端上的附件图标&#xff0c;需要重新启动客户端才…

Mybatis(1)---入门篇单表查询

1.Mybatis介绍 MyBatis 是一款优秀的持久层框架&#xff0c;它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的POJO&#xff08;Plain Old …

Mybatis+Tomcat使用JNDI配置数据源入门

在我们已经有了Mybatis基础的情况下&#xff0c;我们可以使用Tomcat部署web项目1.创建Maven项目 选择webapp 2.配置pom.xml 在pom.xml中添加依赖 这里的依赖比单纯的Mybatis配置多了两个 一个是jsp的依赖&#xff0c;另一个是servlet <dependencies><dependency>&l…

Liferay开发学习Part6:Service Builder

2019独角兽企业重金招聘Python工程师标准>>> 一.什么是Service Builder&#xff1f; Service Builder是liferay IDE提供的一种代码生成方案&#xff0c;开发人员只需编辑一个数据库实体的描述文件&#xff08;XML&#xff09;,即可根据XML文件生成Spring层代码、Hib…

html+css实现响应式布局入门

什么是响应式布局 响应式布局是Ethan Marcotte在2010年5月份提出的一个概念&#xff0c;简而言之&#xff0c;就是一个网站能够兼容多个终端——而不是为每个终端做一个特定的版本。这个概念是为解决移动互联网浏览而诞生的。响应式布局可以为不同终端的用户提供更加舒适的界面…

ajax入门篇

什么是ajax AJAX即“Asynchronous JavaScript and XML”&#xff08;异步的JavaScript与XML技术&#xff09;&#xff0c;指的是一套综合了多项技术的浏览器端网页开发技术。Ajax的概念由杰西詹姆士贾瑞特所提出[1]。 传统的Web应用允许用户端填写表单&#xff08;form&#…

BJRangeSliderWithProgress

2019独角兽企业重金招聘Python工程师标准>>> BJRangeSliderWithProgress 是一个带范围选择的进度条&#xff0c;我用它来做录音的进度指示&#xff0c;并可在选择的范围内进行回放。 转载:http://www.adobex.com/ios/source/details/00000865.htm 转载于:https://my…