C++ std::make_unique和std::make_shared用法

std::make_uniquestd::make_shared 是 C++11 引入的两个辅助函数,用于创建动态分配的智能指针 std::unique_ptrstd::shared_ptr,分别帮助避免了显式使用 newdelete,从而提高代码的安全性和可读性。

std::make_unique:

#include <memory>

int main() {
   
    // 使用
<think>好的,用户想知道C++make_uniquemake_shared的区别。我需要先回忆这两个函数的作用背景。它们都是用来创建智能指针的工厂函数,分别对应unique_ptrshared_ptr。首先,make_unique是在C++14引入的,而make_shared则在C++11就有了。不过用户可能对版本差异不太清楚,需要说明这一点。 接下来,两者的主要区别应该在于所有权模型。unique_ptr是独占所有权,而shared_ptr是共享所有权,引用计数。但用户可能更关心使用这两个函数时的具体差异,比如内存分配方式。记得make_shared会将对象控制块(引用计数等)分配在同一个内存块中,而make_unique只是简单地分配对象本身。这可能影响性能内存使用情况,需要详细解释。 另外,异常安全也是一个点。使用make_sharedmake_unique可以避免因为参数求值顺序导致的潜在内存泄漏,比如当构造函数抛出异常时。这一点需要举例说明,比如对比直接使用newmake函数的情况。 还有初始化方式的不同,比如make_shared不支持自定义删除器,而make_unique同样也不支持,但用户如果需要自定义删除器的话,必须直接使用unique_ptr或shared_ptr的构造函数。这点可能需要提到,但用户的问题可能更关注默认情况。 延迟释放内存的问题,shared_ptr的控制块对象内存一起分配,所以当引用计数归零时,对象内存会被释放,但控制块可能因为weak_ptr的存在而延迟释放。而unique_ptr一旦释放,内存立即回收。这个点对资源管理很重要,特别是涉及大量对象或资源敏感的场景。 还有,类型推导方面,make函数可以自动推导类型,避免重复写类型,提高代码简洁性。比如make_shared<int>(42)比shared_ptr<int>(new int(42))更方便。这也是使用make函数的一个优势,需要强调。 然后,我需要检查是否有相关的引用内容可以支持。在用户提供的引用中,引用[1]提到了unique_ptr,引用[3]提到std::hash支持unique_ptr,引用[4]提到了make_shared的使用示例。这些可以作为引用来源,加强回答的可信度。 用户可能的应用场景,比如什么时候该用哪一个。比如需要共享所有权时用make_shared,独占时用make_unique。性能方面,make_shared可以减少内存分配次数,但可能有内存滞留的问题。需要权衡这些因素。 最后,生成相关问题,比如性能对比、异常安全、自定义删除器等,帮助用户进一步学习。确保回答结构清晰,分点说明,并且符合用户的中文要求,同时正确使用LaTeX格式,比如代码块用反引号,公式用$符号。</think>### C++中`make_unique`与`make_shared`的区别 #### 1. **基本功能与所有权模型** - **`make_unique`** 用于创建`std::unique_ptr`智能指针,表示对象的独占所有权。例如: ```cpp auto ptr = std::make_unique<int>(42); // 独占所有权,不可复制 ``` 其内存分配仅包含对象本身,适合需要明确资源生命周期的场景[^1]。 - **`make_shared`** 用于创建`std::shared_ptr`智能指针,支持共享所有权(通过引用计数)。例如: ```cpp auto ptr = std::make_shared<int>(42); // 共享所有权,可复制 ``` 其内存分配通常将对象控制块(引用计数、弱引用计数等)合并为单次分配,提升效率[^3][^4]。 --- #### 2. **内存分配与性能差异** - **`make_unique`** 分配内存仅用于对象本身,释放时直接销毁对象。 性能与直接使用`new`类似,但通过RAII确保异常安全。 - **`make_shared`** 对象控制块的内存分配合并为单次操作,减少内存碎片分配开销。例如: ```cpp // 单次分配:对象 + 控制块 auto sp = std::make_shared<Widget>(args); ``` 但若存在`weak_ptr`,对象内存可能延迟释放(控制块需等待所有`weak_ptr`释放)。 --- #### 3. **异常安全性** - **`make_unique``make_shared`** 两者均为异常安全的设计。例如: ```cpp process(std::make_unique<Resource>(), calculate_value()); ``` 若`calculate_value()`抛出异常,`make_unique`已分配的内存会自动释放[^4]。 - **对比直接使用`new`** ```cpp process(std::shared_ptr<Resource>(new Resource), calculate_value()); ``` 若`new Resource`后`calculate_value()`抛出异常,可能导致内存泄漏。 --- #### 4. **初始化与类型推导** - **通用语法** `make_unique``make_shared`均支持自动类型推导,简化代码: ```cpp auto u = std::make_unique<std::vector<int>>(10, 20); // 推导为unique_ptr<vector<int>> auto s = std::make_shared<std::string>("Hello"); // 推导为shared_ptr<string> ``` - **不支持自定义删除器** 若需自定义删除器,需显式构造智能指针: ```cpp auto ptr = std::shared_ptr<FILE>(fopen("file.txt", "r"), [](FILE* f) { fclose(f); }); ``` --- #### 5. **应用场景对比** | **场景** | **推荐选择** | **原因** | |------------------------|--------------------|--------------------------------------------------------------------------| | 独占资源,明确生命周期 | `make_unique` | 轻量级,无控制块开销 | | 共享资源,多所有者 | `make_shared` | 合并内存分配,提升性能 | | 需频繁创建/销毁对象 | 视所有权需求选择 | `make_shared`可能因控制块延迟释放导致内存占用增加 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Auto_Car6

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值