本篇笔记包含 Term 18~22。
Term 18:使用 std::unique_ptr 管理具备专属所有权的资源
std::unique_ptr
是只移类型的智能指针,对托管资源有专属所有权- 默认采用 delete 析构资源,也可以使用自定义函数作为删除器(通常是 lambda 函数),使用带状态的 lambda 函数或者函数指针作为删除器会增加智能指针对象大小
std::unique_ptr
容易转换为std::shared_ptr
Term 19:使用 std::shared_ptr 管理具备共享所有权的资源
std::shared_ptr
可复制可移动,计数管理std::shared_ptr
大小是裸指针的两倍,使用动态分配的控制块来管理,计数操作必须是原子性的- 默认采用 delete 析构资源,也可以使用自定义函数作为删除器,删除器型别与
std::shared_ptr
型别无关 - 避免使用裸指针创建
std::shared_ptr
,会创建多余的控制块,析构时出错
Term 20:对于类似 std::shared_ptr 但有可能空悬的指针使用 std::weak_ptr
- 使用
std::weak_ptr
代替可能空悬的std::shared_ptr
,std::weak_ptr::lock
返回一个std::shared_ptr
,若空悬其为空 - 可能会使用
std::weak_ptr
的场景:缓存,观察者列表,避免std::shared_ptr
指针环路
Term 21:优先选用 std::make_unique 和 std::make_shared,而非直接使用 new
- 相比于直接使用 new,make 系列函数代码简短,且异常安全,并且
std::make_shared
和std::allocated_shared
生成的目标码更优 - 不适于使用 make 系列函数的场景包括需要定制删除器,以及期望直接传递大括号初始化物
- 对于
std::shared_ptr
,不建议使用 make 系列函数的额外场景有:自定义内存管理的类;内存紧张的系统,非常大的对象,以及存在比std::shared_ptr
生存期更久的std::weak_ptr
Term 22:Pimpl 习惯用法时,将特殊成员函数的定义放到实现文件中
对于采用 std::unique_ptr
来实现的 pImpl 指针,需要在头文件中声明特种成员函数,但是在实现文件中实现他们(使用 =default
也可以)