【Example】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: 【Example】C++ 标准库智能指针 unique_ptr 与 shared_ptr

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

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

(0)

大家都在看

  • IDEA清空控制台以及Java中运行cmd命令实现清屏操作

    在网上有看到各种的实现方法,比如: Runtime.getRuntime().exec("cls"); &#x6216;&#x8005;&amp…

    Linux 2023年6月6日
    0119
  • 用python实现markdown转html

    1. 前言 现在markdown已经是非常常用的记录工具了,整齐的排版、代码高亮、图片表格样样齐全,同时也支持html标签,是非常好用的一种工具(语法)。 那么今天来分享一下使用p…

    Linux 2023年6月14日
    0113
  • 思科CISCO ASA 5521 防火墙 Ipsec 配置详解

    版本信息: Cisco Adaptive Security Appliance Software Version 9.9(2) Firepower Extensible Opera…

    Linux 2023年6月6日
    082
  • Netty源码解读(四)-读写数据

    读写Channel(READ)的创建和注册 在NioEventLoop#run中提到,当有IO事件时,会调用 processSelectedKeys方法来处理。 当客户端连接服务端…

    Linux 2023年6月7日
    077
  • 最短的可通过编译的C语言程序

    要求:写一个最短的,能通过编译的C语言程序,但不要求能正确运行。 一般人首先想到的是除0。即 除0会引发SIGFPE信号(浮点异常)。 我们也可以删掉return,但是这样做的话编…

    Linux 2023年6月14日
    077
  • nginx源码层面探究request_time、upstream_response_time、upstream_connect_time与upstream_header_time指标具体含义与区别

    背景概述 最近计划着重分析一下线上各api的HTTP响应耗时情况,检查是否有接口平均耗时、99分位耗时等相关指标过大的情况,了解到nginx统计请求耗时有四个指标:request_…

    Linux 2023年6月6日
    091
  • 2018部分

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Linux 2023年6月7日
    074
  • shell 中的EOF

    EOF是(END Of File)的缩写,表示自定义终止符。既然自定义,那么EOF就不是固定的,可以随意设置别名,在linux按ctrl-d 就代表EOF。EOF一般会配合cat能…

    Linux 2023年5月28日
    096
  • Ubuntu18.04 显卡驱动安装(解决各种疑难杂症)

    步骤 下载驱动 准备工作 进行安装 检查安装 下载驱动 首先,我们需要从官网下载显卡驱动。 [En] First of all, we need to download the v…

    Linux 2023年5月27日
    095
  • Flask 易错点

    1.With上下文管理器 常用: with open("file_name","wb") as f: f.write("hello…

    Linux 2023年6月8日
    078
  • linux bash 手册

    1、Linux shell简介 shell是一种特殊的交互式工具,包含了一组内部命令,这些命令可以完成复制文件,移动文件,显示和终止程序等操作。shell的核心是命令行提示符,它允…

    Linux 2023年6月7日
    078
  • web框架底层原理;django介绍

    目录 纯手撸web框架 基于wsgiref模块 优化处理 动静态网页 基于jinja2模板语法 框架请求流程 python主流web框架 *django框架介绍 内容 纯手撸web…

    Linux 2023年6月7日
    076
  • Linux服务器文件打包

    1,一般打包:: 文件路径是相对路径,打包后文件也是相对路径,无论是否添加P参数. 文件目录是绝对路径,但不加P参数打包可能会报错[删除/之类的错误],.加P参数打包正确无错误.打…

    Linux 2023年5月27日
    0103
  • RPA 抖音机器人汇总

    bash;gutter:true; 一、RPA 抖音小店催好评机器人 RPA机器人详情: 1、配置好抖音小店订单号与催好评话术 2、启动抖音小店催好评机器人 3、机器人打开飞鸽客服…

    Linux 2023年6月7日
    078
  • Fastadmin前台Getshell漏洞复现

    Fastadmin前台Getshell漏洞复现 一、简介 FastAdmin是一款基于ThinkPHP5+Bootstrap开发的极速后台开发框架。FastAdmin基于Apach…

    Linux 2023年5月28日
    0107
  • 斐波那契数列前1000项

    斐波那契数列前1000项 {1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,177…

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