C++中的强引用与弱引用

2023-11-17

https://juejin.cn/post/7102838307062546445

1. weak_ptr的原理

weak_ptr 是为了配合 shared_ptr 而引入的一种智能指针,它指向一个由 shared_ptr 管理的对象而不影响所指对象的生命周期,也就是,将一个 weak_ptr 绑定到一个 shared_ptr 不会改变 shared_ptr 的引用计数。不论是否有 weak_ptr 指向,一旦最后一个指向对象的 shared_ptr 被销毁,对象就会被释放。从这个角度看,weak_ptr 更像是 shared_ptr 的一个助手而不是智能指针。

2. 循环引用

(1)什么是循环引用

引用计数实现shared_ptr ,虽然解决了指针独占的问题,但也引来了引用成环的问题,shared_ptr 和 weak_ptr 一起引入了标准库,用来解决循环引用的问题。在 shared_ptr 的使用过程中,当强引用计数为 0 是,就会释放所指向的堆内存。那么当两个 shared_ptr 互相引用,那么它们就永远无法被释放了。

#include <iostream>
#include <memory>

class CB;
class CA {
  public:
    CA() {
      std::cout << "CA()" << std::endl;
    }
    ~CA() {
      std::cout << "~CA()" << std::endl;
    }
    void set_ptr(std::shared_ptr<CB>& ptr) {
      m_ptr_b = ptr;
    }
  private:
    std::shared_ptr<CB> m_ptr_b;
};

class CB {
  public:
    CB() {
      std::cout << "CB()" << std::endl;
    }
    ~CB() {
      std::cout << "~CB()" << std::endl;
    }
    void set_ptr(std::shared_ptr<CA>& ptr) {
      m_ptr_a = ptr;
    }
  private:
    std::shared_ptr<CA> m_ptr_a;
};

int main()
{
  std::shared_ptr<CA> ptr_a(new CA());
  std::shared_ptr<CB> ptr_b(new CB());
  ptr_a->set_ptr(ptr_b);
  ptr_b->set_ptr(ptr_a);
  std::cout << ptr_a.use_count() << " " << ptr_b.use_count() << std::endl;

  return 0;
}

运行结果

yngzmiao@yngzmiao-virtual-machine:~/test$ ./main 
CA()
CB()
2 2

析构函数没有被调用。解决办法 就是将两个类中的一个成员变量改为 weak_ptr 对象,比如将 CB 中的成员变量改为 weak_ptr 对象,即 CB 类的代码如下:

class CB {
  public:
    CB() {
      std::cout << "CB()" << std::endl;
    }
    ~CB() {
      std::cout << "~CB()" << std::endl;
    }
    void set_ptr(std::shared_ptr<CA>& ptr) {
      m_ptr_a = ptr;
    }
  private:
    std::weak_ptr<CA> m_ptr_a;
};

运行结果

yngzmiao@yngzmiao-virtual-machine:~/test$ ./main 
CA()
CB()
1 2
~CA()
~CB()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++中的强引用与弱引用 的相关文章

  • X11 模式对话框

    如何使用 Xlib 在 X11 中创建模式对话框 模态对话框是一个位于应用程序其他窗口之上的窗口 就像瞬态窗口一样 并且拒绝将焦点给予应用程序的其他窗口 在 Windows 中 当试图从模态窗口夺取焦点时 模态也会通过闪 烁模态窗口的标题栏
  • 如何在特定时间以毫秒精度触发 C# 函数?

    我有两台计算机 它们的时间通过 NTP 同步 确保时间仅相差几毫秒 其中一台计算机将通过 TCP 向另一台计算机发送一条消息 以在两台计算机上的未来指定时间启动某个 c 函数 我的问题是 如何在特定时间以毫秒精度 或更好 触发 C 中的函数
  • ASP.NET Web 应用程序中的身份验证遇到问题

    我正在尝试对从登录页面登录我的 Web 应用程序的用户进行身份验证 我正在使用本教程 http support microsoft com kb 301240作为指南 它几乎准确地解释了我希望做什么 但是当我输入用户名和密码时 验证不起作用
  • 在没有 epsilon 的情况下可以将浮点数与 0.0 进行比较吗?

    我知道 要比较两个浮点值 需要使用一些 epsilon 精度 因为它们并不精确 但是 我想知道是否存在边缘情况 我不需要那个 epsilon 特别是 我想知道这样做是否总是安全的 double foo double x if x lt 0
  • 如何从 Qt 应用程序通过 ODBC 连接到 MySQL 数据库?

    我有一个新安装的 MySQL 服务器 它监听 localhost 3306 从 Qt 应用程序连接到它的正确方法是什么 原来我需要将MySQL添加到ODBC数据源 我在遵循这个视频教程后做到了这一点 https youtu be K3GZi
  • opencv中如何去除二值图像噪声?

    将图像转换为二值图像 黑白 后如果有任何噪音怎么办 我消除了那些不需要的噪音 您可以看到下图的黑色区域内有一些白噪声 我该如何去除噪声 使用opencv http img857 imageshack us img857 999 blackn
  • 如何减少 MinGW g++ 编译器生成的可执行文件的大小?

    我有一个简单的 Hello world C 程序 在 Win XP 下由 MinGW g 编译器编译为 500kB 可执行文件 有人说这是由于iostream的库和静态链接libstdc dll Using s链接器选项有点帮助 减少了 5
  • 如何自定义 Google 测试失败消息?

    我编写了一个如下所示的 Google 测试 它将一些计算值与 CSV 文件中预期存储的值进行比较 class SampleTest public testing Test public void setupFile const std st
  • 如何让XmlReader读取C#中的属性?

    我有一个 XML Stream 其中包含以下 XML 内容
  • 我可以将 UseCSharpNullComparisonBehavior 用于单个查询吗?

    我有一个查询 该查询曾经是存储过程 现已转换为 EF 查询 现在已经超时了 使用 SQL Profiler 我可以看到生成的 SQL 的唯一区别是 EF 转变的新行为entity Property value into entity Pro
  • 在 C# 中使用命名空间别名有什么好处? [复制]

    这个问题在这里已经有答案了 使用命名空间别名有什么好处 仅仅是为了简化编码吗 仅当与类发生冲突时我才使用名称空间别名 对我来说 这根本没有简化 我的意见是 如果没有必要 就不要使用
  • valgrind 在 Raspberry Pi 上返回未处理的指令

    我最近一直在尝试在运行 Debian GNU Linux7 0 喘息 的树莓派 型号 b 上使用 valgrind 来调试分段错误 每次我在编译的 C 程序上运行 valgrind 时 都会得到类似以下内容的信息 disInstr arm
  • Type.GetInterfaces() 仅适用于声明的接口

    首先 像这样的问题有很多 也许有些OP甚至在问同样的问题 问题是这些问题的答案 无论是否接受 都没有真正回答这个问题 至少我找不到 如何确定类直接声明的接口 而不是由父级或声明的接口继承的接口 e g interface I interfa
  • 如何同步nosql db(ravendb)中的更改

    我已经开始在 RavenDB 的示例上学习 NoSQL 我从一个最简单的模型开始 假设我们有由用户创建的主题 public class Topic public string Id get protected set public stri
  • 如何检测应用程序正在运行的 .NET 版本?

    我尝试使用Environment Version ToString 确定目标计算机上正在使用什么 NET 框架 但安装了 4 0 版本时 它说我正在使用 NET 2 0 如何检测目标计算机上正在运行的 NET Framework 版本 En
  • 如何从 Access 数据库中读取“是/否”值作为布尔值?

    帮我找回YES NO来自 MS Access 的布尔格式数据类型 我尝试解析它 但它总是返回 false 更新 实际上不是问题抱歉 它确实接受 YES NO 作为布尔值 OleDbconnection dbConnect new OleDb
  • 卸载程序

    我正在尝试使用此代码卸载程序 但它似乎不起作用 我尝试过其他答案 但似乎也不起作用 有人可以帮助我吗 我正在尝试按给定名称 displayName 卸载该程序 例如 我给出 displayName Appname 那么此代码应该从我的计算机
  • 当我的进程被终止时到底会发生什么?

    我有一个包含本机代码和托管代码的混合进程 在 Windows Server 2003 上运行 当我从进程资源管理器中终止进程时 它会进入 100 cpu 的状态 并在消失之前保持这种状态一段时间 有时甚至 10 分钟 在此期间我无法 杀死
  • Boost.asio和异步链,unique_ptr?

    我对异步编程不太熟悉 我有一个问题 我的问题如下 给出 boost asio 中 C 11 的 echo server 示例 http www boost org doc libs 1 60 0 doc html boost asio ex
  • 为什么在构造函数中设置字段是(或不是)线程安全的?

    假设您有一个像这样的简单类 class MyClass private readonly int a private int b public MyClass int a int b this a a this b b public int

随机推荐

  • ue4加载本地版本_【虚幻4】创建本地数据库

    简介 这里我们主要通过使用Data table实现本地数据库 Data table可以用来保存一些用户配置 或者常用变量 或者用来实时更新外部表格数据到虚幻4中 一 创建Data table 1 首先创建Structure结构 这里我已经创
  • 我用什么写Python?

    通常来说 每个程序员都有自己趁手的兵器 代码编辑器 你要是让他换个开发环境 恐怕开发效率至少下降三成 然而 每个人对编辑器的喜好各不相同 甚至引发出诸如 神的编辑器 与 编辑器之神 这种信仰之争 但也正由此可见 个性化的编辑器对于一个程序员
  • 【FICO系列】SAP FICO 凭证错误:BKPFF$PRDCLN800在FI中达到的项目最大编号

    公众号 SAP Technical 本文作者 matinal 原文出处 http www cnblogs com SAPmatinal 原文链接 FICO系列 SAP FICO 凭证错误 BKPFF PRDCLN800在FI中达到的项目最大
  • 无法访问目标主机的原因及其和请求超时的区别

    使用ping命令时经常会遇到这两种情况 就表示网络出了问题 无法访问目标主机的原因 可以看到 无法访问目标主机 是来自一个IP的回复 实际上那个IP是一个路由器 因此 无法访问目标主机 实际上数据是发出去并且收到回复的 只不过收到的回复是别
  • 数据结构和算法(递归概念、迷宫回溯问题和八皇后问题代码实现)

    递归的概念 递归能够做解决什么问题 使用递归时需要注意的问题 递归的第一个应用 迷宫回溯问题 迷宫模拟 定义一个8 7的数组模拟迷宫 1表示围墙 0表示可以走的路 图中左上红圈为起点 右下红圈为终点 利用代码找到从起点到终点的路径 使用递归
  • 【Python】代码实现LL(1),LR(1)上下文无关文法(Stack()类)

    任务要求 针对书上第三章中的表达式文法 采用LL 1 LR 1 进行分析 相关文法 需要进行消除左递归等操作 顺手分享一下课本资源好了 可能不是最新版 排版略有点别扭 后文的书上内容就是指这本书 编译原理 陈意云 文字版 提取码 e0ag
  • Android Studio如何添加工程(project)为library(针对非gradle)

    这篇文章还是针对非gradle build的工程 gradle build有一些差别 在Eclipse要引用别的工程为本工程的library很简单 但是在Android Studio还是稍稍有点小复杂的 那如何引用别的工程为本工程的libr
  • 网络编程——TCP并发服务器模型

    1 多线程中的newfd 能否修改成全局 不行 为什么 因为如果是全局变量 文件描述符就是唯一的 所有的客户端都会在同一个文件描述符通信 2 多线程中分支线程的newfd能否不另存 直接用指针间接访问主线程中的newfd 不行 为什么 如果
  • 微信小程序-仿智行火车票12306

    微信小程序 仿智行火车票12306 微信小程序 仿智行火车票12306 主页有轮播图 有导航栏 有个人中心 可以实现火车票 飞机票 汽车票的选择 适合初学者学习 下面是示例图片 下载链接 https download csdn net do
  • Linux系统图形界面和命令行界面之间的切换

    一 系统不在虚拟机中的情况 使用ctrl alt F1 6切换到命令行界面 ctrl alt F7切换到图形界面 二 系统在虚拟机中的情况 Ctrl Alt shift F1 6切换到命令行界面 使用Alt F7返回到图形界面 注 以上方法
  • hashmap中为什么使用红黑树?

    在回答这个问题之前 我们先了解一下有关二叉树的基本内容 二叉排序树 又称二叉查找树 1 若左子树不为空 则左子树上所有结点的值均小于根结点的值 2 若右子树不为空 则右子树上所有结点的值均大于根节点的值 3 左右子树也为二叉排序树 平衡二叉
  • 2017 ICCV之语义分割:Cascaded Feature Network for Semantic Segmentation of RGB-D Images

    Cascaded Feature Network for Semantic Segmentation of RGB D Images 目前的问题 1 为了计算对象 场景关系的表示 最近大量的分割网络使用一组感受野来丰富卷积特征的文本信息 这
  • book_read_link

    结构性改革 黄奇帆 微信读书 分析与思考 黄奇帆的复旦经济课 黄奇帆 微信读书
  • java通过web3j获取ETH交易明细

    我们在项目里面如果想要得到用户的ETH交易明细怎么做呢 有两种方式 1 直接获取ETH最新块的交易明细 2 通过块获取用户的交易明细 废话不多说 直接贴代码看了 package com example demo web3jLog impor
  • pdf.js引入方式及初始化配置

    官方下载地址 Getting StartedA general purpose web standards based platform for parsing and rendering PDFs http mozilla github
  • actuator--基础--04--Springboot集成

    actuator 基础 04 Springboot集成 代码位置 https gitee com DanShenGuiZu learnDemo tree master actuator learn actuator01 1 代码 1 1 依
  • MongoDB游标

    数据库会使用游标返回 find 的执行结果 游标的客户端实现通常能够在很大程度上对查询的最终输出进行控制 你可以限制结果的数量 跳过一些结果 按任意方向的任意键组合对结果进行排序 以及执行许多其他功能强大的操作 要使用 shell 创建游标
  • 爬虫实战之华为应用市场

    目录 一 需求说明 二 步骤 1 检查当前页面的URL所获得的响应的数据 笨办法 程序验证 不建议 简单办法 抓包 验证 抓包 推荐 动态加载验证 查找页面的信息 2 获取排行页面数据 操作 源码 信息解析 3 详情页面分析 寻找URL 验
  • leetcode 577

    给定一个字符串 s 你需要反转字符串中每个单词的字符顺序 同时仍保留空格和单词的初始顺序 示例 1 输入 s Let s take LeetCode contest 输出 s teL ekat edoCteeL tsetnoc 示例 2 输
  • C++中的强引用与弱引用

    https juejin cn post 7102838307062546445 1 weak ptr的原理 weak ptr 是为了配合 shared ptr 而引入的一种智能指针 它指向一个由 shared ptr 管理的对象而不影响所