深入解析 C++ std::make_shared:原理、优势与最佳实践

在 C++ 开发的世界里,管理动态内存一直是我们面临的核心挑战之一。随着现代 C++ 标准的演进,智能指针的出现极大地改善了我们的开发体验和代码安全性。而在众多智能指针工具中,std::shared_ptr 作为一种共享所有权的智能指针,被广泛应用于复杂的对象生命周期管理中。

但是,你是否思考过这样一个问题:在创建 INLINECODE6d8aa5f5 时,我们是直接使用 INLINECODE9262319f 表达式,还是使用标准库提供的 std::make_shared 工厂函数?

虽然这两种方式最终都能得到一个智能指针,但在性能、安全性以及代码的异常安全性上,它们之间存在着微妙的差异。在这篇文章中,我们将深入探讨 std::make_shared 的工作原理,分析它为何优于传统的构造方式,并通过丰富的代码示例,带你掌握如何在 C++ 项目中有效地利用这一工具来编写更高效、更健壮的代码。

什么 std::make_shared?

简单来说,INLINECODEc3280ae6 是 C++11 标准库 INLINECODE4376ab3a 头文件中引入的一个函数模板。它的主要作用是在单次操作中完成两件事:

  • 在堆上分配内存以创建一个新对象。
  • 创建一个管理该对象的 std::shared_ptr 控制块(包括引用计数)。

它返回一个指向新创建对象的 INLINECODEe2002ce7。相比于手动使用 INLINECODE19e6b10f 关键字,推荐优先使用 std::make_shared,因为它不仅代码更简洁,而且在性能和异常安全性方面表现更佳。

语法与参数

std::make_shared 的基本语法非常直观:

template
std::shared_ptr std::make_shared( Args&&... args );

参数说明:

  • T: 我们想要创建的对象的类型。
  • args…: 传递给 T 类型构造函数的参数列表(支持完美转发)。

返回值:

  • 一个 std::shared_ptr 类型的对象,指向新创建的 T 类型实例。

为什么我们需要 std::make_shared?

你可能会问,既然我们已经有了 shared_ptr 的构造函数,可以直接像这样写代码:

std::shared_ptr ptr(new MyClass(10));

为什么还要多此一举引入 std::make_shared 呢?让我们从三个关键维度来剖析背后的原因。

1. 性能优化:减少内存分配次数

这是 std::make_shared 最大的优势。

使用构造函数(传统方式):

当我们执行 shared_ptr ptr(new int(10)) 时,内存分配实际上发生了两次:

  • 第一次分配:执行 INLINECODE6a878212,在堆上分配内存存储 INLINECODE901bfc76 对象。
  • 第二次分配:shared_ptr 的构造函数需要创建一个控制块,用于存储引用计数、弱引用计数和删除器等信息。这需要在堆上再次分配内存。

这意味着我们执行了两次堆内存分配操作,这在高并发或高性能敏感的场景下,可能会带来额外的开销。

使用 std::make_shared:

当我们执行 auto ptr = make_shared(10) 时,编译器会进行一项优化:

它将控制块对象本身的内存分配合并为一次。也就是说,控制块和对象被分配在同一块连续的内存中。

  • 优势: 减少了内存分配器的调用次数,提高了运行效率。
  • 优势: 提高了内存局部性,因为对象和控制块在内存中是相邻的,CPU 缓存命中率更高。

2. 异常安全性

考虑以下情况:我们需要在一个函数调用中创建对象并传递给智能指针。假设我们有这样一个函数 INLINECODE6f41aa03,它接受一个 INLINECODE535234fe 和其他参数:

// 假设的函数
void processWidget(std::shared_ptr sp, int extraData);

不安全的调用方式:

“INLINECODEa029c469`INLINECODE23ba3880operator newINLINECODE2f4433d5operator newINLINECODEafaf6d23operator deleteINLINECODE07da2913makesharedINLINECODE22e902b4makesharedINLINECODE00582696std::makesharedINLINECODE53cb6cebsharedptrINLINECODE17099226sharedptrINLINECODE43818e58std::makeshared` 吗?”

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。如需转载,请注明文章出处豆丁博客和来源网址。https://shluqu.cn/52669.html
点赞
0.00 平均评分 (0% 分数) - 0