Skip to content

《Effective Modern C++》

第4章 智能指针

条款18:使用std::unique_ptr管理具备专属所有权的资源

要点

  • std::unique_ptr是小巧、高速的、具备只移型别的智能指针,对托管资源实施专属所有权语义。
  • 默认的,资源析构采用delete运算符来实现,但可以指定自定义删除器。具有状态的删除器和采用函数指针实现的删除器会增加unique_ptr型别的对象的尺寸。
  • 将std::unique_ptr容易转换成shared_ptr。

条款19:使用std::shared_ptr管理具备共享所有权的资源

要点

  • shared_ptr提供了方便的手段,实现了任意资源在共享所有权语义下进行生命周期管理的垃圾回收。
  • 与unique_ptr相比,shared_ptr的尺寸通常是裸指针尺寸的两倍,它还会带来控制块的开销,并要求原子化的引用计数操作。
  • 默认的资源析构通过delete运算符进行,但同时也支持用户自定义删除器。删除器的型别对shared_ptr的型别没有影响。
  • 避免使用裸指针型别的变量来创建shared_ptr。

条款20:对于类似std::shared_ptr但有可能空悬的指针使用weak_ptr

要点

  • 使用weak_ptr来代替可能空悬的shared_ptr。
  • weak_ptr可能的用武之地包括缓存,观察者列表,以及避免shared_ptr指针环路。

条款21:优选选用std::make_unique和std::make_shared,而非直接使用new

要点

  • 相比直接使用new表达式,make系列函数消除了重复代码、改进了异常安全性,并且对于make_shared和std::allcoated_shared而言,生成的目标代码会尺寸更小、速度更快。
  • 不适于使用make系列函数的场景包括:需要使用定制删除器,以及期望直接传递大括号初始化。

条款22:使用Pimpl习惯用法时,将特殊成员函数的定义放到实现文件中

Pimpl(point to implementation)把某类的数据成员用一个指涉到某实现类(或结构体)的指针替代,然后把原来放在主类中的数据成员放置到实现类中,并通过指针间接访问这些数据成员。

要点

  • Pimpl惯用法通过降低类的客户和类实现者之间的依赖性,减少了构建遍数。
  • 对于采用unique_ptr来实现的pImpl指针,须在类的头文件中声明特种成员函数,但在实现文件中实现它们。即使默认函数实现有着正确的行为,也必须这样做。
  • 上述建议只适用于unique_ptr,但不适用shared_ptr。