C++ 中的智能指针

C++ 提供了四个智能指针模板类, 分别是: auto_ptr, unique_ptr, shared_ptrweak_ptr. (auto_ptr是 C++98 提供的解决方案, C++11 已经将其摒弃, 并提供了另外三种解决方案). 这三个智能指针模板都定义了类似指针的对象, 可以将new获得(直接或间接)的地址赋给这种对象. 当智能指针过期时, 其析构函数将使用delete来释放内存. (要创建智能指针对象, 需要包含头文件<memory>)

三种智能指针的区别?

  • auto_ptr: 当进行赋值时, 会将旧指针的所有权转让, 使得 对于特定的对象, 只能有一个智能指针可以拥有它.
  • unique_ptr: 当进行赋值时, 会将旧指针的所有权转让, 使得 对于特定的对象, 只能有一个智能指针可以拥有它. unique_ptr 相比于 auto_ptr 会执行更加严格的所有权转让策略
  • shared_ptr: 通过引用计数(reference counting), 跟踪引用特定特定对象的智能指针数. 当发生赋值操作时, 计数增1, 当指针过期时, 计数减1. 仅当最后一个指针过期时, 才调用 delete.
  • weak_ptr: 不控制对象声明周期的智能指针, 它指向一个 shared_ptr 管理的对象, 而进行内存管理的只有 shared_ptr. weak_ptr 主要用来帮助解决循环引用问题, 它的构造和析构不会引起引用计数的增加或者减少. weak_ptr 一般都是配合 shared_ptr 使用, 通常不会单独使用.

unique_ptr 和 auto_ptr 的区别?

  • 所有权转让机制不同: auto_ptr 允许通过直接赋值进行转让, 但是这样会留下危险的 悬挂指针, 容易使得程序在运行阶段崩溃. unique_ptr 仅仅允许将临时右值进行赋值, 否则会在编译阶段发生错误, 这样更加安全(编译阶段错误比潜在的程序崩溃更安全).
  • 相比于 auto_ptr 和 share_ptr, unique_ptr 可以使用new[]分配的内存作为参数: std::unique_ptr<double[]> pda(new double(5));

如何选择合适的只能指针?

如果程序要使用多个指向同一个对象的指针, 应选择shared_ptr, 这样的情况包括:

  • 对于智能指针数组, 用辅助指针来标识最大值或最小值的情况
  • 很多 STL 算法都支持复制和赋值操作, 这些操作可用于 shared_ptr, 但不能用于 unique_ptrauto_ptr.

如果程序不需要多个指向同一个对象的指针, 则可以使用unique_ptr, 如果函数使用new分配内存, 并返回指向该内存的指针, 将其返回类型声明为unique_ptr是不错的选择, 这样, 所有权将转让给接受返回值的unique_ptr.