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

std::make_shared简化智能指针 `std::shared_ptr` 的创建过程,并提高性能(减少内存分配次数,提高缓存命中率)

std::make_shared 是 C++ 标准库中的一个函数模板,用于简化智能指针 std::shared_ptr 的创建过程。引入 std::make_shared 的主要原因是提高代码的安全性、性能和可读性。以下是详细分析:


1. 安全性提升

避免显式调用 new 导致的错误

在不使用 std::make_shared 的情况下,我们通常手动调用 new 来分配内存并初始化对象:

std::shared_ptr<MyClass> ptr(new MyClass(arg1, arg2));

这种方式容易引发以下问题:

  • 异常安全问题:如果在 newstd::shared_ptr 构造之间抛出异常,会导致资源泄漏。
  • 内存管理错误:手动调用 new 容易忘记释放资源。

使用 std::make_shared 后,这些问题都被封装到函数内部,减少了手动操作的可能性:

auto ptr = std::make_shared<MyClass>(arg1, arg2);

避免显式分配内存导致的错误

std::make_shared 内部会同时完成内存分配和对象构造,确保两者是一致的。而直接使用 std::shared_ptr(new T) 可能会出现分配内存失败但对象已经构造完成的情况,从而导致内存泄漏。


2. 性能优化

减少一次内存分配

普通方式创建 std::shared_ptr 时,通常需要两次内存分配:

  1. 分配一块内存存储 std::shared_ptr 的控制块(包含引用计数等元信息)。
  2. 分配另一块内存存储实际的对象。

std::make_shared 将这两块内存合并成一次分配,提高了内存分配效率。这尤其在频繁创建对象时会有显著的性能提升。

缓存局部性

由于 std::make_shared 将控制块和对象存储在一起,访问控制块时的缓存命中率更高,从而提升了程序的整体性能。


3. 提高代码可读性和简洁性

使用 std::make_shared 可以使代码更加简洁和直观:

// 普通方式
std::shared_ptr<MyClass> ptr(new MyClass(arg1, arg2));// 使用 make_shared
auto ptr = std::make_shared<MyClass>(arg1, arg2);

后者不仅减少了代码量,还避免了重复书写 new,使代码更易于阅读和维护。


4. 示例对比

普通方式
std::shared_ptr<int> ptr(new int(42)); // 显式调用 new
*ptr = 10; // 修改对象
使用 make_shared
auto ptr = std::make_shared<int>(42); // 自动分配和构造
*ptr = 10; // 修改对象

可以看到,std::make_shared 的语法更加简洁且不易出错。


5. 总结

std::make_shared 的优点包括:

  • 提高安全性(避免资源泄漏和异常问题)。
  • 提高性能(减少内存分配次数,提高缓存命中率)。
  • 提高代码可读性和简洁性。

因此,在现代 C++ 编程中,推荐优先使用 std::make_shared 来创建 std::shared_ptr


参考资料

  • C++ Reference: std::make_shared
  • Effective Modern C++: Item 14
http://www.xdnf.cn/news/998641.html

相关文章:

  • Tomcat 和 Spring MVC
  • SQL进阶之旅 Day 29:NoSQL结合使用策略
  • docker-自动启动java 包
  • 使用VSCode开发FastAPI指南
  • Python 实现 Web 请求与响应
  • VSCode - Trae 插件关闭弹出框代码补全
  • 【C++学习笔记】 std::atomic 拷贝构造错误解析
  • docker-compose容器单机编排
  • el-select+el-tree实现树形下拉选择
  • tabs页签嵌套表格,切换表格保存数据不变并回勾
  • CSS 外边距合并(Margin Collapsing)问题研究
  • Karate 与Playwright的比较和融合
  • spring boot项目整合mybatis实现多数据源的配置
  • RAG Food Project
  • GAN+ECA注意力机制实现图像超分辨率重建
  • ESP32-C3FH4X—低功耗、高集成度的 MCU 系统级芯片 (SoC)
  • 基于数据库实现配置管理和定时任务启停
  • 强化学习:策略梯度概念
  • word用endnote插入国标参考文献
  • 在 Flutter 项目中iOS 的 App 图标和 App 名称 的设置
  • 探索 Excel-to-JSON:高效数据转换的利器
  • Linux Alias 魔法:命令行效率提升秘籍
  • R语言缓释制剂QBD解决方案之四
  • RK3588 + Ubuntu24.04 部署 rknn 模型——不用[特殊字符]版全流程教程
  • 管家婆软件下载中心-管家婆软件辉煌安装包下载、应用程序、最新版软件
  • STL难记忆却常用的用法集合(持续更新中)
  • 自动驾驶系统研发系列—AI大模型驱动的智能座舱:从概念到落地的工程解析
  • MonkeyOCR: 基于结构-识别-关系三元组范式的文档解析
  • 客户端登录not foud的问题解决
  • PostgreSQL 用户名大小写处理规则