make_shared与new

news2024/12/28 20:22:08

        假设有这么个类:

class A
{
    private:
        int b;
    public:
        A(int c):b(c) { cout << "call constructor..." << endl;}
        ~A() { cout << "call destructor..." << endl;}
        int getValue() { return b;}
};

        当创建指向 A 对象的智能指针 shared_ptr 时,很多地方都提到 new 至少执行两次分配,一次用于对象 A 的创建,一次用于智能指针 shared_ptr 的控制块,而如果用 make_shared() 方法通常只需执行一次分配,效率上有所提升。

        这点 Herb Sutter 在他的博客 🔗GotW #89 Solution: Smart Pointers 也有提到:

First, with make_shared the code is simpler. Write for clarity and correctness first.

Second, using make_shared is more efficient. The shared_ptr implementation has to maintain housekeeping information in a control block shared by all shared_ptrs and weak_ptrs referring to a given object...

If you allocate the object separately via a raw new expression, then pass it to a shared_ptr, the shared_ptr implementation has no alternative but to allocate the control block separately...

We’d like to avoid doing two separate allocations here. If you use make_shared to allocate the object and the shared_ptr all in one go, then the implementation can fold them together in a single allocation...

        下面我们从汇编层面看看二者区别,主方法中代码如下:

shared_ptr<A> sn(new A(5));
shared_ptr<A> sm = make_shared<A>(6);

        第一行对应汇编语句如下:

0x0000000100000e64 <+20>:    call   0x100003914
0x0000000100000e69 <+25>:    mov    %rax,%rcx
0x0000000100000e6c <+28>:    mov    %rax,%rdx
0x0000000100000e6f <+31>:    mov    $0x5,%esi
0x0000000100000e74 <+36>:    mov    %rax,%rdi
0x0000000100000e77 <+39>:    mov    %rcx,-0x48(%rbp)
0x0000000100000e7b <+43>:    mov    %rdx,-0x50(%rbp)
0x0000000100000e7f <+47>:    call   0x100000f20 <_ZN1AC1Ei>
0x0000000100000e84 <+52>:    jmp    0x100000e89 <main()+57>
0x0000000100000e89 <+57>:    movl   $0x0,-0x28(%rbp)
0x0000000100000e90 <+64>:    mov    -0x28(%rbp),%edx
0x0000000100000e93 <+67>:    lea    -0x18(%rbp),%rdi
0x0000000100000e97 <+71>:    mov    -0x50(%rbp),%rsi
0x0000000100000e9b <+75>:    call   0x100000f50 <_ZNSt3__110shared_ptrI1AEC1IS1_EEPT_NS_9enable_ifIXsr17__compatible_withIS4_S1_EE5valueENS2_5__natEE4typeE>
0x0000000100000ee3 <+147>:   call   0x10000390e
0x0000000100000ee8 <+152>:   jmp    0x100000f07 <main()+183>
0x0000000100000f07 <+183>:   mov    -0x20(%rbp),%rdi
0x0000000100000f0b <+187>:   call   0x100003878
0x0000000100000f10 <+192>:   ud2

        先是调用了地址在 0x100003914 处的方法,试着通过 info 去看并没查到对应方法名:

(gdb) info symbol 0x100003914
No symbol matches 0x100003914.

        查看代码位置:

lucas@lucasdeMacBook-Pro testCpp % objdump -h test

test:   file format mach-o 64-bit x86-64

Sections:
Idx Name             Size     VMA              Type
  0 __text           00002a27 0000000100000e50 TEXT
  1 __stubs          000000cc 0000000100003878 TEXT
  2 __stub_helper    000000f6 0000000100003944 TEXT
  3 __gcc_except_tab 00000274 0000000100003a3c DATA
  4 __cstring        0000006b 0000000100003cb0 DATA
  5 __const          00000102 0000000100003d1b DATA
  6 __unwind_info    000001d8 0000000100003e20 DATA
  7 __got            00000068 0000000100004000 DATA
  8 __const          000000c8 0000000100004068 DATA
  9 __la_symbol_ptr  00000110 0000000100008000 DATA
 10 __data           00000008 0000000100008110 DATA

        方法地址位于 __stubs Section__stubs 可理解为动态库链接的桩,具体方法名可在 MachOView 中查看:

        根据地址 0x100003914 可看到对应的 value_Znwm,即 operator new() 方法,在执行几次 mov 指令后还要依次调用如下几个方法。

(gdb) info symbol 0x100000f20
A::A(int) in section .text of /Users/lucas/Documents/study/code/testCpp/test
(gdb) info symbol 0x100000f50
std::__1::shared_ptr<A>::shared_ptr<A>(A*, std::__1::enable_if<__compatible_with<A, A>::value, std::__1::shared_ptr<A>::__nat>::type) in section .text of /Users/lucas/Documents/study/code/testCpp/test

        最后还要调用值 _ZdlPv 对应的 operator delete() 方法。可以看到通过 new 创建 shared_ptr 对象一共要执行近 20 条汇编指令,而通过 make_shared() 方法呢?

0x0000000100000ea0 <+80>:    movl   $0x6,-0x3c(%rbp)
0x0000000100000ea7 <+87>:    lea    -0x38(%rbp),%rdi
0x0000000100000eab <+91>:    lea    -0x3c(%rbp),%rsi
0x0000000100000eaf <+95>:    call   0x100000f80 <_ZNSt3__1L11make_sharedI1AJiEvEENS_10shared_ptrIT_EEDpOT0_>
0x0000000100000eb4 <+100>:   jmp    0x100000eb9 <main()+105>
0x0000000100000eb9 <+105>:   lea    -0x38(%rbp),%rdi

        无需再调用 operator new()operator delete() 方法,且只需执行一次分配即可,总共也就 6 条指令。

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

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

相关文章

【测绘程序设计】——附合导线近似平差

附合导线(Connecting Traverse,CT)近似平差是测绘专业九大核心专业基础课——《数字地形测量学》中的重点内容,其程序设计也是测绘学子必修的课程设计之一。本文分享了测绘程序设计——附合导线近似平差(C++/MFC版),相关源代码(完整工程,包含测试数据)及使用示例(结果…

CLion开发环境的完全解析(QT开发?STM32?顺便速通cmake

文章目录下载与安装主题推荐编辑器与clang-format设置鼠标滚轮改变字体大小clang-format的使用我的 .clang-format 配置编译工具链设置编译工具链的添加与解释cmake配置项的添加与解释cmake的使用与实战常用的cmake变量&#xff08;入门&#xff09;常用的cmake命令&#xff08…

融合通信系统建设建议(华脉智联内参一)

各行业融合通信系统建设建议 让通信融合信息无阻 题记&#xff1a;目前各个行业都已建设了视频监控系统、内部电话系统、无线对讲机系统、公共广播系统、会场音频系统、视频会议系统等。这些通信系统各自解决不同的用户需求&#xff0c;随着技术的发展&#xff0c;以及融合通信…

腾讯安全连续三年列为Gartner在线反欺诈市场指南全球代表厂商

近日&#xff0c;全球研究机构Gartner发布了2022《在线反欺诈市场指南》&#xff08;Market Guide for Online Fraud Detection&#xff09;。腾讯安全凭借天御&#xff08;TenDI&#xff09;金融风控被列为全球代表性厂商&#xff0c;这也是腾讯安全连续第三次被列入该报告。随…

洛谷千题详解 | P1031 [NOIP2002 提高组] 均分纸牌【C/C++、pascal、Java语言】

博主主页&#xff1a;Yu仙笙 专栏地址&#xff1a;洛谷千题详解 目录 题目描述 输入格式 输出格式 输入输出样例 解析&#xff1a; C源码&#xff1a; pascal源码&#xff1a; pascal源码2&#xff1a; Java源码&#xff1a; ------------------------------------------------…

很穷的top2农村男博士要不要嫁?

这个问题最近在知乎上面很火&#xff0c;经常能刷到&#xff0c;具体背景如下&#xff1a;我自己家也是农村的&#xff0c;家里比较穷&#xff0c;我就读的学校肯定比不上top2&#xff0c;但也还不错&#xff0c;是个C9&#xff0c;所以这个问题想和大家简单聊一下我的看法。知…

JavaScript刷LeetCode拿offer-栈相关题目

1. 栈是什么&#xff1f; 一种先进后出的数据结构&#xff1b;JavaScript没有栈的结构&#xff1b;可以用array实现栈的功能 入栈 push(x);出栈 pop(); const stack [];// 入栈 stack.push(1); stack.push(2);// 出栈 const item1 stack.pop(); const item2 stack.pop();2…

GC日志分析

1.写在前面 前段时间一位读者面了阿里&#xff0c;在二面中被问到 GC 日志分析&#xff0c;感觉回答的不是很好&#xff0c;过来找我复盘&#xff0c;大致听了他的回答&#xff0c;虽然回答出了部分&#xff0c;但是没抓到重点。 GC 日志分析算是 JVM 调优中比较难的部分&…

【python数据分析】对淘商品类母婴购物数据进行分析(含完整源码)

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 又到了学Python时刻~ 一、数据集 ​ 今天我们来看一个来着阿里云天池的数据集:淘母婴购物数据,有两个csv文件: 1、mum_baby.csv 它包含了953个孩子的生日和性别信息&#xff0c;这些信息是由淘或tian猫的消费者提供的…

足球视频AI(四)——队伍与裁判人员分类

一、基础概念 足球比赛中人员为&#xff1a;A队11人、B队11人、裁判&#xff0c;其中我们暂时不研究守门员。 需要将球场中的人员分类&#xff0c;并呈现在2D看板中。 1.1识别目标&#xff1a; 1&#xff09;球场中的白队 2&#xff09;球场中的蓝队 3&#xff09;球场中的…

剑指offer----C语言版----第九天

目录 1. 剪绳子 1.1 题目描述 1.2 基础知识 1.2.1 动态规划 1.2.2 贪婪算法 1.3 思路一&#xff1a;动态规划 1.4 思路二&#xff1a;贪婪算法 1.5 思路一的优化 1. 剪绳子 原题链接&#xff1a;剑指 Offer 14- I. 剪绳子 - 力扣&#xff08;LeetCode&#xff09;http…

无约束优化:Hessian-Free Optimization 拟牛顿类算法(BFGS,L-BFGS)

文章目录无约束优化&#xff1a;Hessian-Free Optimization 拟牛顿类算法&#xff08;BFGS&#xff0c;L-BFGS&#xff09;为什么要用拟牛顿算法割线方程严格凸且光滑函数的BFGS算法非凸但光滑函数的BFGS算法L-BFGS算法非凸非光滑函数的BFGS算法参考文献无约束优化&#xff1a;…

LInux僵尸进程的解决方法

文章目录僵尸进程是如何出现的&#xff1f;如何防止僵尸进程产生&#xff1f;使用wait函数使用waitpid函数阻塞等待非阻塞等待——轮询僵尸进程出现后如何解决&#xff1f;僵尸进程是如何出现的&#xff1f; 一个进程在退出后&#xff0c;操作系统会释放该进程对应的资源&…

网络舆情监测管理制度及处置机制,网络舆情监测服务项目实时方案?

舆情监测通常包括搜集、分析和报告舆论信息的过程。搜集信息的途径包括网络新闻、社交媒体、博客、论坛等&#xff0c;分析信息的方法包括自然语言处理、数据挖掘、模糊属性决策分析等。接下来TOOM舆情监测小编带您简单了解网络舆情监测管理制度及处置机制&#xff0c;网络舆情…

奈奎斯特采样定理(Nyquist)

采样定理在1928年由美国电信工程师H.奈奎斯特首先提出来的&#xff0c;因此称为奈奎斯特采样定理。1933年由苏联工程师科捷利尼科夫首次用公式严格地表述这一定理&#xff0c;因此在苏联文献中称为科捷利尼科夫采样定理。1948年信息论的创始人C.E.香农对这一定理加以明确地说明…

VirtualBox+Vagrant快速搭建linux虚拟环境

VirtualBoxVagrant快速搭建linux虚拟环境 1.下载安装VirtualBox 下载 Virtual Box 官网: https://www.virtualbox.org/ 2.BIOS 里修改设置开启虚拟化设备支持(f2, f10) 参考: https://jingyan.baidu.com/article/ab0b56305f2882c15afa7dda.html 3.安装 Virtual Box&#xff…

【自学Python】Windows Python交互式运行

Windows Python交互式运行 Windows Python交互式运行教程 安装好 Python 之后&#xff0c;Python 都会提供一个 Python 命令行工具&#xff0c;就叫 python。 python 命令行工具不仅能用于运行 Python 程序&#xff0c;也可作为一个交互式解释器&#xff0c;即开发者可以在该…

9种 分布式ID生成方式

一、为什么要用分布式ID&#xff1f; 在说分布式ID的具体实现之前&#xff0c;我们来简单分析一下为什么用分布式ID&#xff1f;分布式ID应该满足哪些特征&#xff1f; 1、什么是分布式ID&#xff1f; 拿MySQL数据库举个栗子&#xff1a; 在我们业务数据量不大的时候&#…

AcWing算法提高课:区间DP

两种实现方式 循环式 一般对于一维的DP问题可以应用。 for(len 1; len < n; len)for(l 1; l len-1 < n; l)r l len - 1;//枚举方案数记忆化搜索式 一般在二维DP中使用 循环也倒是可以&#xff0c;但是层数太多&#xff0c;所以使用记忆化进行实现。 常见策略 …

深入解读Netty 底层核心源码,全面分析Netty特新

前言 Netty 是一款基于 NIO&#xff08;非阻塞 I/O&#xff09;开发的网络框架&#xff0c;与传统 BIO 相比&#xff0c;它的并发性能得到了很大的提高&#xff0c;而且更加节省资源。Netty 不仅封装了 NIO 操作的很多细节&#xff1b;在设计上还基于灵活、可扩展的事件驱动模…