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

make_unique

在 C++ 中,make_unique 是 C++14 引入的一个辅助函数,用于更安全、更便捷地创建 std::unique_ptr 智能指针。相较于直接使用 new 表达式初始化 unique_ptrmake_unique 的安全性主要体现在以下几个方面:

1. 避免资源泄漏(异常安全)

直接使用 new 的风险

当用 new 手动创建对象并传递给智能指针时,若初始化过程中发生异常(例如构造函数抛出异常或后续代码出错),可能导致资源未被智能指针接管而泄漏。
示例(风险场景)

// 假设 func() 可能抛出异常
std::unique_ptr<int> p(new int(42));  // 安全:直接初始化
std::unique_ptr<int> p1(new int(42), func);  // 安全:deleter是栈上对象
std::unique_ptr<int> p2(new int(42), std::bind(func, get_data()));  // 危险!
  • std::unique_ptr<int> p2(...) 中,表达式执行顺序为:
    1. 执行 get_data() 获取参数(可能抛出异常)。
    2. 执行 new int(42) 分配内存(可能抛出 bad_alloc)。
    3. 执行 std::bind(func, ...) 创建deleter。
    4. 将指针和deleter传入 unique_ptr 构造函数。
  • 风险点:若步骤1或步骤3抛出异常,new int(42) 返回的指针尚未被 unique_ptr 接管,导致内存泄漏。
make_unique 的安全性

make_unique 通过单一表达式完成内存分配、对象构造和智能指针对象的创建,确保在异常发生时资源能被正确释放。
示例(安全版本)

auto p = std::make_unique<int>(42);  // 等价于 unique_ptr<int>(new int(42))
auto p2 = std::make_unique<int>([](int* x){ func(x); });  // 自定义deleter
  • make_unique 内部会直接将 new 表达式的结果传递给 unique_ptr 构造函数,保证内存分配和智能指针初始化在同一作用域内完成,避免中间步骤的异常导致泄漏。

2. 防止裸指针误用

直接使用 new 的隐患

手动使用 new 时,可能意外将裸指针暴露给外部,破坏智能指针的封装性,导致悬空指针或双重释放问题。
示例(错误用法)

int* raw = new int(42);
std::unique_ptr<int> p1(raw);
std::unique_ptr<int> p2(raw);  // 非法!两个智能指针管理同一裸指针,导致双重释放
make_unique 的封装性

make_unique 直接返回 unique_ptr 对象,不暴露裸指针,从源头避免上述问题。
示例(安全用法)

auto p1 = std::make_unique<int>(42);
auto p2 = p1;  // 非法!unique_ptr不可拷贝,避免误操作
auto p3 = std::move(p1);  // 合法!通过移动语义转移所有权

3. 更简洁的语法,减少人为错误

直接使用 new 的冗余

初始化 unique_ptr 时需显式写出类型,容易因类型不匹配导致编译错误。
示例(冗余代码)

std::unique_ptr<std::vector<int>> vec(new std::vector<int>{1, 2, 3});
// 需重复书写类型 `std::vector<int>`
make_unique 的类型推导

make_unique 支持模板类型推导,代码更简洁且不易出错。
示例(类型推导)

auto vec = std::make_unique<std::vector<int>>({1, 2, 3});
// 自动推导为 unique_ptr<std::vector<int>>,无需重复书写类型

4. 对数组和聚合类型的友好支持

数组初始化(C++14+)

make_unique 支持直接创建数组类型的 unique_ptr,避免手动处理 [] 的问题。
示例

// 分配包含5个int的数组(值初始化为0)
auto arr = std::make_unique<int[]>(5);  // 等价于 unique_ptr<int[]>(new int[5]())
arr[0] = 10;// 列表初始化(C++17+)
auto arr2 = std::make_unique<int[]>({1, 2, 3});  // 数组大小为3
聚合类型初始化(C++17+)

对于没有构造函数的聚合类型(如 struct),make_unique 支持直接初始化成员。
示例

struct Point { int x, y; };  // 聚合类型
auto p = std::make_unique<Point>(Point{1, 2});  // C++14写法
auto p2 = std::make_unique<Point>(1, 2);         // C++17简化写法(直接传递成员值)

5. 与其他智能指针和库的兼容性

make_unique 是 C++ 标准库的一部分,与 std::make_shared(用于 shared_ptr)风格统一,便于代码维护和团队协作。

  • 例如,在需要返回智能指针的函数中,使用 make_unique 可确保接口的一致性:
    std::unique_ptr<MyClass> createObject() {return std::make_unique<MyClass>(arg1, arg2);  // 简洁且安全
    }
    

总结:make_unique 的核心优势

特性make_unique直接使用 new + unique_ptr
异常安全单一表达式完成分配和初始化,避免泄漏可能因初始化顺序导致泄漏
封装性不暴露裸指针,禁止非法拷贝可能意外传递裸指针,导致双重释放
语法简洁性自动类型推导,减少冗余需显式指定类型,容易出错
数组/聚合支持原生支持数组和聚合类型初始化需手动处理 [] 和构造函数
代码一致性make_shared 风格统一,易于维护风格不统一,可能混合裸指针和智能指针

何时不使用 make_unique

  • 需要自定义deleter的非默认构造场景
    若deleter需要在 unique_ptr 构造时动态生成(如依赖外部参数),仍需手动使用 new
    示例
    // 自定义deleter依赖外部函数指针
    void(*deleter)(int*) = my_custom_deleter;
    auto p = std::unique_ptr<int>(new int(42), deleter);
    // 无法用make_unique直接生成,需手动处理
    
  • C++14 之前的编译器
    若项目需兼容 C++11,需手动实现类似 make_unique 的辅助函数(C++11 标准库未包含 make_unique,但可自行实现)。

最佳实践

  • 优先使用 make_unique:只要场景允许,尽量用 make_unique 创建 unique_ptr,避免手动操作 new
  • 结合RAII原则:将资源管理完全交给智能指针,避免在作用域内显式调用 delete
  • 避免裸指针传递:函数参数和返回值尽量使用智能指针或引用,减少裸露资源的风险。

通过 make_unique,C++ 提供了一种更安全、更现代的动态内存管理方式,显著降低了传统 new/delete 模式下的常见错误。

相关文章:

  • 启动metastore时报错MetaException(message:Version information not found in metastore
  • NodeJS全栈WEB3面试题——P7工具链 测试
  • 池中锦鲤的自我修养,聊聊蓄水池算法
  • 代码随想录算法训练营第六天| 242.有效的字母异位词 、 349. 两个数组的交集 、 202. 快乐数 、1. 两数之和
  • 2023年12月6级第一套第一篇
  • 英文投资理财源码挖矿源码投资理财系统源码(源码下载)
  • 线程安全与线程池
  • 审计- 1- 审计概述
  • python打卡训练营打卡记录day43
  • 【存储基础】【VFS】inodedentrysuper_block以及它们之间的关系
  • ER图递归关系画法,chen氏
  • 【JAVA】注解+元注解+自定义注解(万字详解)
  • 计算机组成原理——CPU的功能和基本结构
  • SQL进阶之旅 Day 12:分组聚合与HAVING高效应用
  • 【Pytorch学习笔记】模型模块06——hook函数
  • 蓝云APP:云端存储,便捷管理
  • 第2篇:数据库连接池原理与自定义连接池开发实践
  • 列表推导式(Python)
  • 题目 3230: 蓝桥杯2024年第十五届省赛真题-星际旅行
  • 通讯录Linux的实现
  • 产品推广方案模板/厦门百度seo点击软件
  • 企业型网站和展示型网站的区别/seo资料站
  • 无锡做网站企业/西地那非片的功能主治
  • 怎样在各b2b网站做推广/引流推广网站平台
  • 可信网站行业验证必须做吗/无锡网站优化公司
  • 郑州做公司网站/视频营销