【Effective Modern C++】第四章 智能指针:18. 使用独占指针管理具备专属所有权的资源

std::unique_ptr 的特性

  1. 轻量高效:默认删除器下,大小和原始指针一致,操作(如解引用)的执行效率和原始指针几乎无差别,可用于内存 / 性能敏感场景。
  2. 独占所有权 :一个非空的 std::unique_ptr 独占指向的资源,仅可移动(move-only)、不可拷贝------ 拷贝会导致两个指针同时管理同一资源,析构时重复销毁;移动则会将所有权从源指针转移到目标指针(源指针置空)。
  3. 自动析构 :析构时会自动销毁指向的资源(默认调用 delete),即便程序因异常、提前返回等非典型流程终止(除异常传播到 main 外、调用abort/exit等极端情况),也能保证资源释放,避免内存泄漏。

应用场景

  1. 工厂函数返回值

    适合作为继承体系对象的工厂函数返回类型(如 Investment 基类 + Stock/Bond 派生类),调用方独占工厂创建的堆对象所有权,无需手动管理销毁,示例中通过makeInvestment返回unique_ptr<Investment>,自动释放派生类对象。

  2. 接管 C 风格 API 的堆数组

    std::unique_ptr 有数组版本 std::unique_ptr<T[]>(仅适配 C 风格堆数组),但优先推荐std::array/std::vector等容器,仅在必须接管原始数组时使用。

自定义删除器

  1. 使用方式 :可自定义销毁逻辑(如先打日志再delete),删除器可以是 lambda、函数对象或普通函数,需将删除器类型作为std::unique_ptr的第二个模板参数。

  2. 注意事项

    • 管理继承体系对象时,基类必须声明虚析构函数,否则通过基类指针删除派生类对象会未定义行为;
    • 删除器影响unique_ptr大小:无状态 lambda(不捕获变量)无额外开销,函数指针 / 有状态删除器会增加其大小(通常从 1 个指针大小变为 2 个),优先用 lambda 实现自定义删除器。
  3. C++14 优化:支持函数返回类型推导,可将删除器定义在工厂函数内部,代码更简洁封装。

特殊形式与兼容性

  1. 两种形式区分

    • std::unique_ptr<T>:管理单个对象,支持*/->解引用;
    • std::unique_ptr<T[]>:管理数组,支持[]下标访问;
  2. 无缝转换为std::shared_ptr

    std::unique_ptr 可直接赋值给std::shared_ptr,工厂函数返回unique_ptr既保证调用方的高效独占使用,也不限制调用方转为共享所有权(shared_ptr),是工厂函数返回类型的最优选择。

总结

  1. std::unique_ptr 是轻量、高效的 "独占所有权" 智能指针,仅可移动,析构自动释放资源;
  2. 自定义删除器灵活,但无状态 lambda 开销最小,管理继承对象需基类虚析构;
  3. 核心优势是适配工厂函数场景,且可无缝转为std::shared_ptr,兼顾独占 / 共享所有权需求。

原著在线阅读地址

相关推荐
Chester_19994 小时前
CSP202203C.计算资源调度器
开发语言·数据结构·c++·蓝桥杯
会周易的程序员5 小时前
给 PLC 写一个字节码虚拟机:STVM 虚拟机架构设计
开发语言·c++·虚拟机·软plc·iec61131·stvm
小灰灰搞电子6 小时前
完全驾驭 Qt 与数据库:C++ ORM 框架 QxOrm 原理与实践指南
数据库·c++·qt
QT界面美化性能优化6 小时前
QT+AI:使用AI技术为QT应用程序赋能
c++·人工智能·qt·opencv·qt教程·qt6.3
学习星球8 小时前
单调栈——从“找下一个更大的“到柱状图中的最大矩形
数据库·c++·算法·leetcode·xcode
小灰灰搞电子9 小时前
C++ 引用折叠详解
c++
布莱克6059 小时前
数组详解:定义、作用、应用场景及与链表的区别(C/C++ 代码讲解)
c语言·开发语言·c++·数组
牛油果子哥q10 小时前
C++内存池与对象池精讲:内存碎片、自定义分配器、对象池实现、STL allocator原理、工程落地与性能对比
java·开发语言·c++
万法若空11 小时前
C/C++ 类型别名定义方式对比
java·c语言·c++
小小晓.12 小时前
C++ 值类别与完美转发深度剖析:从左值右值到 std::forward 源码解密
开发语言·c++·算法