C++ 标准库智能指针 unique_ptr 与 shared_ptr

【概念直接搬运Docs】C 样式编程的一个主要 bug 类型是内存泄漏。 泄漏通常是由于为分配的内存的调用失败引起的 delete new 。 现代 C++ 强调”资源获取即初始化”(RAII) 原则。 其理念很简单。 资源(堆内存、文件句柄、套接字等)应由对象”拥有”。 该对象在其构造函数中创建或接收新分配的资源,并在其析构函数中将此资源删除。 RAII 原则可确保当所属对象超出范围时,所有资源都能正确返回到操作系统。

为了支持对 RAII 原则的简单采用,C++ 标准库提供了三种智能指针类型:std::unique_ptrstd::shared_ptrstd::weak_ptr。 智能指针可处理对其拥有的内存的分配和删除。 下面的示例演示了一个类,其中包含一个数组成员,该成员是在调用 make_unique() 时在堆上分配的。 对和的 new 调用 deleteunique_ptr 类封装。 当 widget 对象超出范围时,将调用 unique_ptr 析构函数,此函数将释放为数组分配的内存。

在现代 c + + 编程中,标准库包含智能指针,这些指针用于帮助确保程序不会出现内存和资源泄漏,并具有异常安全。

====================================

unique_ptr

unique_ptr 类型智能指针在设计上最显著的特点是内部托管的指针一旦被创建就不能被任何形式的复制给另一个unique_ptr,只可以被移动给另一个unique_ptr。unique_ptr 没有拷贝构造函数,因此不能用于赋值。该指针最常用的情况是单例模式和编译防火墙的封装。当一个 std::unique 生命周期结束时,将释放所托管的内存,也就意味着,如果它作为一个局部变量托管一个对象,对象的生命周期也仅限于当前作用域范围,调用 reset() 或 operator= 时也会释放原有内存。

成员函数表:

名称 作用 operator= 赋值,如果已经存在托管的内存,会释放掉原有内存。 operator[] 数组下标形式访问。 release 返回一个指向被管理对象的裸指针,并释放所有权。 reset 释放原有对象内存,如果传递了参数,则替换为新指定的指针。 swap 交换两个 std::unique_ptr 对象 get 返回所托管对象的裸指针。

返回所托管对象的析构删除器。

检查是否有关联的被管理对象。

解引用。

解引用。

额外注解:

只有非 const 的 unique_ptr 能转移被管理对象的所有权给另一 unique_ptr 。若对象的生存期为 const std ::unique_ptr 所管理,则它被限定在创建指针的作用域中。 std::unique_ptr 常用于管理对象的生存期,包含:

  • 通过正常退出和经由异常退出两者上的受保证删除,提供异常安全,给处理拥有动态生存期的对象的类和函数

  • 传递独占的拥有动态生存期的对象的所有权到函数

  • 从函数获得独占的拥有动态生存期对象的所有权

  • 作为具移动容器的元素类型,例如保有指向动态分配对象的指针的std::vector (例如,若想要多态行为)
    std::unique_ptr 可为不完整类型 T 构造,例如用于改善用作 pImpl 手法中柄的用途。若使用默认删除器,则 T 必须在代码中调用删除器点处完整,这发生于析构函数、移动赋值运算符和 std::unique_ptrreset 成员函数中。(相反地, std::shared_ptr 不能从指向不完整类型的裸指针构造,但可于 T 不完整处销毁)。注意若 T 是类模板特化,则以 unique_ptr 为运算数的使用,如 !p ,因 ADL 而要求 T 的形参完整。
    T 是某基类 B 的导出类,则 std ::unique_ptr
    不同于 std::shared_ptr , std::unique_ptr 可通过任何满足可空指针 (NullablePointer) 的定制柄类型管理对象。例如,这允许管理位于共享内存,但提供定义 typedef boost::offset_ptr pointer; 或其他缀饰指针的 Deleter 的对象。

与 shared_ptr 搭配的 weak_ptr

weak_ptr 设计上与 shared_ptr 搭配使用, 因为 shared_ptr 存在一个问题,就是循环引用计数递增而导致的内存泄漏

比如说:

这种情况,两个node对象互相引用着对方,最终导致资源无法被释放。所以有时候需要访问 shared_ptr 自身,而不是它所托管的资源。

所以 weak_ptr 的作用就来了:

为什么呢?

因为 share_ptr 是强引用,强引用是只要被引用的对象还存活那么这个引用也一定会存在。

而 weak_ptr 是弱引用,弱引用是虽然对象还活着,但是这个引用则可有可无。

所以,weak_ptr 的作用就是作为一个 “观察者” 访问 shared_ptr 本身,而不是 shared_ptr 所托管的资源。

同时也意味着,weak_ptr 只能访问它所观察的shared_ptr 本身,而不能访问 share_ptr 托管的资源, 所以,它不会增加 shared_ptr 的引用计数

成员函数表:

名称 作用 operator= 赋值 reset 释放被管理对象的所有权 swap 交换被管理对象 use_count 返回当前所管理的对象引用计数。

检查被引用的对象是否已删除 lock 创建管理被引用的对象的

提供基于拥有者大小顺序的比较

额外补充:

std::bad_weak_ptr 是 std::shared_ptr 以 std::weak_ptr 为参数的构造函数,在 std::weak_ptr 指代已被删除的对象时,作为异常抛出的对象类型。

#include 
#include 
int main()
{
    std::shared_ptr<int> p1(new int(42));
    std::weak_ptr<int> wp(p1);
    p1.reset();
    try {
        std::shared_ptr<int> p2(wp);
    } catch(const std::bad_weak_ptr& e) {
        std::cout << e.what() << '\n';
    }
}

Original: https://www.cnblogs.com/airchip/p/15890186.html
Author: 芯片烤电池
Title: C++ 标准库智能指针 unique_ptr 与 shared_ptr

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/642580/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球