当前位置: 首页 > news >正文

【C++ 基础 】C++14 中为什么 make_shared / make_unique 更安全?

目录标题

  • C++14 中为什么 `make_shared` / `make_unique` 更安全?
    • 一、最核心的原因:避免裸 `new`
    • 二、异常安全更好
    • 三、代码更简洁,也更不容易写错
    • 四、`make_shared` 通常效率更高
      • 直接写法
      • `make_shared` 写法
    • 五、`make_unique` 同样推荐使用
    • 六、什么时候不一定用 `make_shared`?
      • 1. 需要自定义删除器
      • 2. 不希望对象和控制块一起分配
    • 七、实战建议
      • 1. 能用 `make_unique` 就优先用 `make_unique`
      • 2. 需要共享所有权时,再用 `make_shared`
      • 3. 尽量避免直接写裸 `new`
    • 八、总结
    • 参考示例
      • 推荐写法
      • 不太推荐的写法
  • 结语


C++14 中为什么make_shared/make_unique更安全?

在 C++14 里,创建智能指针时,通常更推荐使用:

autop1=std::make_shared<MyClass>(args);autop2=std::make_unique<MyClass>(args);

而不是直接写:

std::shared_ptr<MyClass>p1(newMyClass(args));std::unique_ptr<MyClass>p2(newMyClass(args));

很多初学者会问:
“它们不都是创建智能指针吗?为什么make_版本更安全?”

这篇文章就来总结一下。


一、最核心的原因:避免裸new

先看两种写法:

std::shared_ptr<T>p(newT(args));
autop=std::make_shared<T>(args);

第二种写法最大的优势是:不需要手动写new

为什么这很重要?

因为一旦代码里出现裸new,就意味着对象先被创建出来,然后再交给智能指针接管。
如果这个过程中出现异常、重构失误,或者写法稍复杂一点,就有可能出现资源泄漏。

make_shared/make_unique把“创建对象”和“交给智能指针管理”合并成了一步,风险更小。


二、异常安全更好

这是make_风格最经典的优点。

看下面这段代码:

func(std::shared_ptr<T>(newT()),g());

表面上看没问题,但在 C++14 中,函数参数的求值顺序并没有规定

也就是说,编译器可能这样执行:

  1. 先执行new T()
  2. 再执行g()
  3. 最后再构造shared_ptr

如果第 2 步中的g()抛出异常,那么刚才new T()创建出来的对象,就可能来不及交给shared_ptr管理,从而发生泄漏。

而如果写成:

func(std::make_shared<T>(),g());

那么make_shared<T>()内部会把对象创建和智能指针构造打包成一个完整过程。
要么成功返回一个shared_ptr,要么失败时自动清理,不会把裸指针暴露在外面。

这就是它“更安全”的关键所在。


三、代码更简洁,也更不容易写错

直接构造智能指针时,类型通常要写两遍:

std::shared_ptr<MyType>p(newMyType(1,2));

make_shared只需要写一次:

autop=std::make_shared<MyType>(1,2);

这种好处看起来只是“简洁”,但实际上它也提升了代码安全性:

  • 少写一次类型,减少重复
  • 修改类型时不容易漏改
  • 构造参数更直观
  • 阅读成本更低

这属于工程层面的安全
也就是说,它不一定是运行时安全问题,但能明显减少人为失误。


四、make_shared通常效率更高

除了安全之外,make_shared还有一个常见优势:内存分配更高效

直接写法

std::shared_ptr<T>p(newT(args));

通常需要两次内存分配:

  1. 给对象T分配内存
  2. shared_ptr的控制块分配内存(引用计数、删除器等)

make_shared写法

autop=std::make_shared<T>(args);

很多实现中,make_shared可以把对象和控制块放在同一块内存里,一次分配完成。

这样做的好处是:

  • 分配次数更少
  • 性能通常更好
  • 内存局部性更好
  • 少一次分配失败的机会

当然,这一点更多是“高效”,不是最核心的“安全”。


五、make_unique同样推荐使用

在 C++14 中,std::make_unique已经正式可用,所以创建unique_ptr时也建议优先写成:

autop=std::make_unique<T>(args);

而不是:

std::unique_ptr<T>p(newT(args));

原因和make_shared类似:

  • 避免裸new
  • 异常安全更自然
  • 代码更简洁
  • 所有权表达更清晰

尤其是unique_ptr本来就表示“独占所有权”,配合make_unique会非常自然。


六、什么时候不一定用make_shared

虽然大多数情况下推荐make_shared,但也不是绝对。

1. 需要自定义删除器

例如:

std::shared_ptr<T>p(newT,custom_deleter);

这种场景下,make_shared就不方便直接处理。


2. 不希望对象和控制块一起分配

make_shared通常会把对象和控制块放在同一块内存里。
这在大多数时候是优点,但某些特殊场景下反而可能不是最优。

例如:

  • 对象很大
  • weak_ptr存活时间很长

此时即使最后一个shared_ptr已经销毁,只要控制块还因为weak_ptr存在而保留,那么整块内存的释放策略就会受到影响。

这属于偏进阶的话题,日常开发里一般不用太纠结。


七、实战建议

在日常 C++14 开发中,可以记住一个简单原则:

1. 能用make_unique就优先用make_unique

因为它表达独占所有权最直接。

autop=std::make_unique<MyClass>();

2. 需要共享所有权时,再用make_shared

autop=std::make_shared<MyClass>();

3. 尽量避免直接写裸new

除非你确实有特殊需求,比如:

  • 自定义删除器
  • 特殊内存管理策略
  • 必须分离对象和控制块

八、总结

C++14 中make_shared/make_unique更安全,核心原因可以概括为四点:

  • 避免裸new
  • 异常安全更好
  • 对象创建后立即交给智能指针管理
  • 代码更简洁,不容易写错

其中最重要的一点其实是:

它把“创建资源”和“接管资源”合并成了一个更安全的整体。

所以在大多数情况下,可以记住一句很实用的话:

能用make_shared/make_unique,就尽量不要手写new


参考示例

推荐写法

#include<memory>classTest{public:Test(intx){}};intmain(){autop1=std::make_unique<Test>(10);autop2=std::make_shared<Test>(20);}

不太推荐的写法

#include<memory>classTest{public:Test(intx){}};intmain(){std::unique_ptr<Test>p1(newTest(10));std::shared_ptr<Test>p2(newTest(20));}

结语

在我们的编程学习之旅中,理解是我们迈向更高层次的重要一步。然而,掌握新技能、新理念,始终需要时间和坚持。从心理学的角度看,学习往往伴随着不断的试错和调整,这就像是我们的大脑在逐渐优化其解决问题的“算法”。

这就是为什么当我们遇到错误,我们应该将其视为学习和进步的机会,而不仅仅是困扰。通过理解和解决这些问题,我们不仅可以修复当前的代码,更可以提升我们的编程能力,防止在未来的项目中犯相同的错误。

我鼓励大家积极参与进来,不断提升自己的编程技术。无论你是初学者还是有经验的开发者,我希望我的博客能对你的学习之路有所帮助。如果你觉得这篇文章有用,不妨点击收藏,或者留下你的评论分享你的见解和经验,也欢迎你对我博客的内容提出建议和问题。每一次的点赞、评论、分享和关注都是对我的最大支持,也是对我持续分享和创作的动力。

最后,想特别推荐一下我出版的书籍——《C++编程之禅:从理论到实践》。这是对博主C++ 系列博客内容的系统整理与升华,无论你是初学者还是有经验的开发者,都能在书中找到适合自己的成长路径。从C语言基础到C++20前沿特性,从设计哲学到实际案例,内容全面且兼具深度,更加入了心理学和禅宗哲理,帮助你用更好的心态面对编程挑战。
本书目前已在京东、当当等平台发售,推荐前往“清华大学出版社京东自营官方旗舰店”选购,支持纸质与电子书双版本。希望这本书能陪伴你在C++学习和成长的路上,不断精进,探索更多可能!感谢大家一路以来的支持和关注,期待与你在书中相见。


阅读我的CSDN主页,解锁更多精彩内容:泡沫的CSDN主页

http://www.jsqmd.com/news/640866/

相关文章:

  • Mac上5分钟搞定K3s+kubeflow:开发测试环境搭建全流程(含资源分配避坑指南)
  • 基于V4L2与DRM框架:在RK3588上实现USB摄像头到MIPI屏幕的低延迟图像通路
  • 乡村基蒸菜系列减脂餐外卖有优惠吗?2026这份美团半价活动攻略记得收藏 - 资讯焦点
  • 临床执业医师老师推荐:请看这篇报道 - 医考机构品牌测评专家
  • MedGemma 1.5医疗助手实战:本地部署+思维链解读全攻略
  • 2026跨城包车攻略:聊城到济南包车多少钱多少钱?携程百事通实价揭秘,拒绝隐形消费 - 土星买买买
  • 手把手教你部署MiniCPM-V-2_6:支持图文视频对话,开箱即用
  • 1-1杰理蓝牙SOC的UI配置开发方法
  • 一次性无纺布源头厂家哪家好点 - 企业推荐官【官方】
  • 2026年必知!连续式切丁机生产厂家哪家更胜一筹? - 企业推荐官【官方】
  • 靠谱的河南电缆公司
  • 深度解析CD66e (癌胚抗原相关细胞粘附分子5):分子机制与靶向药物研发进展
  • 【GaussTech技术专栏】GaussDB逻辑解码技术原理
  • 利用MSSQL解析优化数据库性能,提升效率,驱动业务创新与稳定发展
  • AgentCPM深度研报助手Matlab数据分析联动:模型结果深度可视化
  • 3分钟搞定讯飞云 ASR 中英语音识别:MicroPython+uPyPI一键安装驱动包
  • 东莞塑形内衣加盟代理全攻略 塑身内衣塑身衣美体内衣调整型健康塑形产后塑身衣加盟指南 - 企业推荐官【官方】
  • 刚体转动:从概念到解题的思维跃迁
  • 大模型方向有哪些具体岗位?一文带你了解!
  • 【2026Q2最紧急技术升级】电商搜索正面临多模态拐点,SITS2026已验证的4步迁移路线图
  • 2026长沙财税公司口碑推荐:企业主真实评价,这几家值得收藏 - 小征每日分享
  • 手势识别大模型已突破临界点:2026奇点大会公布的7项核心参数,90%企业尚未适配
  • Aviator表达式求值器踩坑实录:从‘Hello World’到自定义函数的5个实战技巧
  • 2026济南大巴包车全攻略:携程百事通揭秘,团体出行省心密码 - 土星买买买
  • 别再死记公式了!用积分器电路理解‘电容充电’的物理本质(附常见误区分析)
  • 河南塑美达塑业 —— 电商 / 外贸 / 出口食品包装源头工厂,全国源头各工厂对比优选 - 企业推荐官【官方】
  • RimSort终极指南:免费开源边缘世界模组管理器完全教程
  • 3分钟学会:如何用Unlock-Music解锁你收藏的加密音乐文件?
  • 专业靠谱债务重组公司|深圳荣德源金服:银/行/理/财经理债务暴雷,100万低息置换助其破局重生 - 企业推荐官【官方】
  • AIGlasses OS Pro 智能视觉系统GitHub开源项目实战:贡献视觉模型工具包