C++ 提供了四个智能指针模板类, 分别是: auto_ptr
, unique_ptr
, shared_ptr
和weak_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_ptr
和auto_ptr
.
如果程序不需要多个指向同一个对象的指针, 则可以使用unique_ptr
, 如果函数使用new
分配内存, 并返回指向该内存的指针, 将其返回类型声明为unique_ptr
是不错的选择, 这样, 所有权将转让给接受返回值的unique_ptr
.