clean C++ 学习笔记 第五章 01

智能指针

智能指针实际上是一个重载了"*"、"->"、"[]"等特殊符号来达到类似指针使用方法效果的一个类。其作用是避免传统指针使用时,忘记释放,造成内存泄漏。用这种新式指针,满足RAII原则(资源申请初始化——"构造时获得,析构时释放")的同时,使使用形式简单化。

c++ 11中的3个智能指针类型:

  1. std::unique_ptr

    当我们独占资源的所有权的时候,可以使用 std::unique_ptr 对资源进行管理——离开 unique_ptr 对象的作用域时,会自动释放资源。

    通俗来说,一个对象一次只能由std::unique_ptr<T>的 一个实例来管理,当这个对象被std::unique_ptr<T>的其他实例管理时,原实例会被置为空。

    正因如此,不允许调用std::unique_ptr<T>的拷贝构造函数,

使用形式如下:

{
    std::unique_ptr<int> uptr = std::make_unique<int>(200);
    // 离开 uptr 的作用域的时候自动释放内存
}
  1. std::shared_ptr

    std::shared_ptr可以由许多共享std::shared_ptr<T>的实例的接管者。std::shared_ptr<T>内置了一个引用计数器,监视当前有多少个std::shared_ptr<T>实例。当最后一个实例被销毁,智能指针就会释放持有的资源。

    std::shared_ptr<T>可以拷贝,也可以用std::move强行移动它指向的资源。但被移动后,此std::shared_ptr变量就会变成nullptr

    一个 shared_ptr 对象的内存开销要比裸指针的 unique_ptr 对象略大:

      std::cout << sizeof(int*) << std::endl;  // 输出 8
      std::cout << sizeof(std::unique_ptr<int>) << std::endl;  // 输出 8
      std::cout << sizeof(std::shared_ptr<int>) << std::endl;  // 输出 16
    

    shared_ptr 需要维护的信息有两部分:

    1.指向共享资源的指针。

    2.引用计数等共享资源的控制信息——实际是维护一个指向控制信息的指针。所以,shared_ptr 对象需要保存两个指针。

    当我们创建一个 shared_ptr 时,其实现一般如下:

    std::shared_ptr<T> sptr1(new T);
    

img

复制一个 shared_ptr :

std::shared_ptr<T> sptr2 = sptr1;

img

  1. std::weak_ptr

    如何检测shared_ptr<T>管理的资源是否有效呢,此时可以使用std::weak_ptr, 一个 std::weak_ptr 对象可以看做是 std::shared_ptr 对象管理着的资源的观察者,它不影响共享资源的生命周期:

    1. 如果需要使用 weak_ptr 正在观察的资源,可以将 weak_ptr 提升为 shared_ptr

    2. shared_ptr 管理的资源被释放时,weak_ptr 会自动变成 nullptr

img

当 shared_ptr 析构并释放共享资源的时候,只要 weak_ptr 对象还存在,控制块就会保留,weak_ptr 可以通过控制块观察到对象是否存活。

img

参考自 1. https://zhuanlan.zhihu.com/p/150555165 2. 《clean C++》

原文地址:https://www.cnblogs.com/LLBoy/p/15564519.html