0

0

C++中make_shared有什么好处_C++智能指针内存分配优化原理【底层】

穿越時空

穿越時空

发布时间:2026-02-12 17:37:27

|

683人浏览过

|

来源于php中文网

原创

make_shared 更高效,因其一次内存分配同时构建控制块和对象,避免了new+shared_ptr的两次分配及数据局部性差的问题,并具备强异常安全保证。

c++中make_shared有什么好处_c++智能指针内存分配优化原理【底层】

make_shared 为什么比 new + shared_ptr 构造更高效

make_shared 的核心优势在于「一次内存分配完成控制块和对象的布局」,而手动用 new 构造再传给 shared_ptr 需要两次分配:一次给对象,一次给控制块(含引用计数、弱引用计数等)。这不仅多一次系统调用开销,还破坏了数据局部性——对象和它的控制块可能分散在不同内存页。

典型反例:

auto p1 = std::shared_ptr<int>(new int(42)); // 两次分配

对应等价但高效的写法:

auto p2 = std::make_shared<int>(42); // 一次分配,对象紧贴控制块之后

控制块内存布局差异直接影响 cache 命中率

标准库实现(如 libstdc++ 和 libc++)中,make_shared 分配的内存块结构通常是:control_block_header + aligned_storage_for<t></t>。这意味着访问 shared_ptr::get() 指向的对象时,控制块往往已在同一 cache line 中——尤其在频繁拷贝、析构或调用 use_count() 的场景下,减少 cache miss 效果明显。

立即学习C++免费学习笔记(深入)”;

10Web
10Web

AI驱动的WordPress网站自动构建器,托管和页面速度助推器

下载

手动构造则无法保证这种布局,控制块和对象地址差可能达 KB 级别。

  • 若对象很小(如 intstd::string 小字符串优化态),make_shared 节省的分配次数和提升的局部性收益最显著
  • 若类型重载了 operator newmake_shared 仍会调用全局 ::operator new 分配整块内存,不会触发类特化版本——这点常被忽略
  • 不支持直接传递自定义删除器(make_shared 固定使用 default_delete);需自定义删除器时只能退回到 shared_ptr 构造函数

make_shared 对异常安全的隐式保障

当构造函数可能抛异常时,make_shared<t>(args...)</t> 是强异常安全的:要么完整构造成功并返回 shared_ptr,要么不分配、不调用构造函数、不泄漏资源。而手动写法存在隐患:

auto p = std::shared_ptr<T>(new T(a, b, c)); // 若 T(a,b,c) 抛异常,new 已分配内存但未被 shared_ptr 管理 → 泄漏

这是因为 new T(...) 表达式本身在 shared_ptr 构造函数体执行前就完成了对象构造——异常发生在构造期间,shared_ptr 构造函数甚至没机会接管原始指针。

  • make_shared 内部用 ::operator new 分配足够空间后,在该内存上用 placement new 构造对象,整个过程被封装在函数内部,异常路径已处理
  • 注意:如果 T 的构造函数抛异常,make_shared 会自动释放之前分配的整块内存(含控制块空间)

哪些情况不能用 make_shared

不是所有场景都能替换。以下情形必须绕过 make_shared

  • 需要自定义删除器(例如文件句柄、C API 资源):std::shared_ptr<file>(fopen(...), fclose)</file> 无法用 make_shared
  • 类禁用了 operator new(且未提供匹配的 placement new)
  • 需要将同一个对象同时交给多个 shared_ptr 管理(即 aliasing constructor 场景),此时必须用原始指针构造
  • 对象类型没有 public 构造函数,但 friend 类可访问其私有构造 —— make_shared 无法穿透访问权限(它在外部调用)

控制块与对象是否共分配,是编译器无关的语义保证,但具体内存对齐、头部大小属于实现细节。实际压测中,高频创建/销毁小对象时,make_shared 的吞吐量通常高出 10%–30%,主要来自分配器压力下降和 cache 友好性。真正要注意的,是它不解决循环引用问题,也不改变 shared_ptr 本身的线程安全边界。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

708

2023.08.02

fclose函数的用法
fclose函数的用法

fclose是一个C语言和C++中的标准库函数,用于关闭一个已经打开的文件,是文件操作中非常重要的一个函数,用于将文件流与底层文件系统分离,释放相关的资源。更多关于fclose函数的相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

336

2023.11.30

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

509

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

214

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1550

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

640

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

862

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

814

2024.04.29

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

4

2026.02.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 9.2万人学习

C 教程
C 教程

共75课时 | 4.7万人学习

C++教程
C++教程

共115课时 | 17.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号