【笔记】C++中的智能指针

参考自《effective morden c++》

裸指针的缺点

  1. 无法知道指向的是单个对象还是一个数组.
  2. 无法知道使用完之后是否需要析构,即是否拥有指向的对象.
  3. 无法知道应当如何析构(使用 delete 还是专门的函数)
  4. 无法知道单个析构还是数组析构.
  5. 不能保证只析构一次。少了会导致内存泄漏,多了是UB.
  6. 无法检查指针空悬.

std::unique_ptr

  1. 足够小、足够快,几乎和裸指针相同.
  2. 是一个只移类型(不可复制),当其析构时,内部的对象也会被析构。
  3. 可以自定义删除器,会略微增大尺寸.
  4. 自定义删除器的类型需要加入到模板参数中
  5. 不建议用其存储数组,可以使用 vector, array 等.
  6. 可以方便地转为 shared_ptr.

std::shared_ptr

  1. 尺寸是裸指针的两倍,因为内部既包含一个资源指针,又包含一个控制块的指针.
  2. 引用计数是原子性的.
  3. 自定义删除器不需要加入到模板参数.
  4. 控制块包括:引用计数、弱计数、其他数据(自定义删除器等)
  5. 不要用保存好的裸指针来创建 shared_ptr,直接从 new 创建。因为会创建一个新控制块.
  6. 由上,从 this 创建指针也是很危险的,可以让类 T 继承 std::enable_shared_from_this<T>,然后使用 shared_from_this 函数创建.
    这里的设计模式叫 奇异递归模板模式.
  7. 不要用它保存数组

std::wake_ptr

  1. 用于 sp 的辅助,不能直接获取指向的资源.
  2. expired() 判断是否失效.
  3. 如果需要线程安全地判断是否失效并且没失效时返回一个 shared_ptr,可以使用
    • lock(),如果失效返回的 sp 为空
    • 直接创建,如果失效会返回异常.
  4. 用途:缓存观察是否失效,观察者模式,避免 sp 循环依赖.
  5. 控制块里的弱计数记录 wp 的数量,当 sp 和 wp 数量全部为0后,控制块才会被析构。

std::make_unique, std::make_shared

  1. make_unique 是 C++ 14的部分,可以自己写一个(暂略)
  2. 优先使用 make_shared,因为速度更快:控制块和托管对象处在同一内存区域。
  3. 不适用的情况包括:自定义删除器,直接传递大括号初始化。
  4. 使用 make_shared 后,如果 sp 数量已经为0,但还有 wp,那么内存不会被释放(对象已经被析构,控制块未被析构).
发布了382 篇原创文章 · 获赞 317 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/m0_37809890/article/details/104701539