std::make_shared通过一次内存分配同时创建对象和控制块,减少开销、提升缓存局部性;保证异常安全,避免参数求值顺序导致的内存泄漏;并支持类型推导,使代码更简洁安全,是创建shared_ptr的首选方法。

使用 std::make_shared 相比于直接使用 new 配合 std::shared_ptr 构造,主要优势体现在内存分配效率和代码安全性上。核心在于:它将控制块(control block)与实际对象的内存分配合并为一次操作,减少了动态内存分配的开销。
内存分配次数优化
std::shared_ptr 内部需要两个部分:
- 指向实际对象的指针
- 控制块:包含引用计数、弱引用计数等管理信息
当这样写时:
std::shared_ptr会发生两次独立的内存分配:
立即学习“C++免费学习笔记(深入)”;
- new MyClass 分配对象内存
- shared_ptr 构造时再分配控制块内存
而使用:
auto ptr = std::make_shared则只进行一次内存分配。这块内存同时包含:
- MyClass 对象的存储空间
- 内联的控制块
这种合并分配减少了 heap 分配调用次数,降低内存碎片,提升缓存局部性,尤其在高频创建场景下性能更优。
异常安全保证
考虑函数调用:
系统优势: 1、 使用全新ASP.Net+c#和三层结构开发. 2、 可生成各类静态页面(html,htm,shtm,shtml和.aspx) 3、 管理后台风格模板自由选择,界面精美 4、 风格模板每月更新多套,还可按需定制 5、 独具的缓存技术加快网页浏览速度 6、 智能销售统计,图表分析 7、 集成国内各大统计系统 8、 多国语言支持,内置简体繁体和英语 9、 UTF-8编码,可使用于全球
虽然 new 和 shared_ptr 构造看似原子,但参数求值顺序未定义。可能执行顺序为:
- 执行 new MyClass(内存已分配)
- 调用 bar()(可能抛出异常)
- shared_ptr 构造未执行,导致内存泄漏
使用 make_shared 可避免此问题:
foo(std::make_shared因为 make_shared 调用本身是单个表达式,要么成功返回 shared_ptr,要么抛出异常但不会造成资源泄漏。
类型推导与代码简洁性
make_shared 利用模板参数推导,避免重复书写类型名:
auto ptr = std::make_shared相比:
std::shared_ptr更简洁,减少出错可能,也便于重构。
基本上就这些。make_shared 在性能、安全、可读性上都优于手动 new 配合 shared_ptr,应作为首选方式,除非需要自定义删除器或无法满足继承场景的多态构造需求。









