深入理解Qt的隐式共享机制

在Qt中,一个关键的性能优化特性是其数据结构的隐式共享机制,这在Qt的文档和API中常被称为“隐式共享”或“写时复制(Copy-On-Write, COW)”。本文将详细介绍这一机制,并通过QString类的实现代码和相应的反汇编代码来阐释其工作原理。

隐式共享的定义和优点

隐式共享是一种内存管理策略,它允许多个对象共享相同的数据副本,直到某个对象需要修改这些数据时才进行实际的数据复制。这种策略的优点包括:

  • 减少内存使用:多个对象可以共享同一个数据副本,而不是每个对象都持有一个数据副本。
  • 提高性能:减少数据复制的需要,从而降低程序的总体资源消耗。
  • 代码简化:开发者不需要关心数据如何被共享或复制,所有这些都由Qt框架自动管理。

隐式共享在Qt中的实现

在Qt中,很多基本数据类型,如QString、QList、QByteArray等,都实现了隐式共享。以下是QString类中赋值操作符的源码,可以直观了解隐式共享机制的实现:

QString &QString::operator=(const QString &other) noexcept
{other.d->ref.ref();if (!d->ref.deref())Data::deallocate(d);d = other.d;return *this;
}

代码解释

  1. other.d->ref.ref();

增加源对象(other)数据的引用计数。
因为在赋值后,目标对象和源对象都引用了相同的内存数据,所以对应的引用计数需要增加。

  1. if (!d->ref.deref()) Data::deallocate(d);

通过deref()函数递减目标对象(d)的引用计数,并返回递减后是否仍有引用(如果还有其他引用,则返回true;如果此次操作后引用计数变为0,则返回false)。如果返回false,说明没有其他QString对象再引用这块数据了,那就需要调用Data::deallocate()来释放这块内存。
因为目标对象在赋值后将指向新的内存数据,那么原来的数据引用计数需要递减,如果递减后变成0,那就说明没有对象在使用这块内存,需要释放,否则会导致内存泄漏。

反汇编代码示例说明

源码

QString sa = "hello";
QString sb = sa;
sb[0] = 'H';

反汇编

    QString sa = "hello";
00007FF65A72461B  lea         rdx,[__xt_z+214h (07FF65A729CB4h)]  
00007FF65A724622  lea         rcx,[sa]  
00007FF65A724627  call        qword ptr [__imp_QString::QString (07FF65A72F170h)]  
00007FF65A72462D  nop  QString sb = sa;
00007FF65A72462E  lea         rdx,[sa]  
00007FF65A724633  lea         rcx,[sb]  
00007FF65A724638  call        qword ptr [__imp_QString::QString (07FF65A72F188h)]  
00007FF65A72463E  nop  sb[0] = 'H';
00007FF65A72463F  xor         r8d,r8d  
00007FF65A724642  lea         rdx,[rsp+88h]  
00007FF65A72464A  lea         rcx,[sb]  
00007FF65A72464F  call        qword ptr [__imp_QString::operator[] (07FF65A72F178h)]  
00007FF65A724655  mov         dl,48h  
00007FF65A724657  mov         rcx,rax  
00007FF65A72465A  call        qword ptr [__imp_QCharRef::operator= (07FF65A72F168h)]

详细说明

  1. 在执行QString sb = sa;代码是,反汇编代码可以看出,先将sasb两个对象的地址加载到两个寄存器中,然后调用QString的拷贝构造函数。
  2. 在执行sb[0] = 'H';时,反汇编代码的最后一行代码,调用了QCharRef::operator=()赋值操作符,那么我们需要知道该赋值操作符具体做了什么:
inline QCharRef &operator=(QChar c)
{using namespace QtPrivate::DeprecatedRefClassBehavior;if (Q_UNLIKELY(i >= s.d->size)) {
#ifdef QT_DEBUGwarn(WarningType::OutOfRange, EmittingClass::QCharRef);
#endifs.resize(i + 1, QLatin1Char(' '));} else {
#ifdef QT_DEBUGif (Q_UNLIKELY(!s.isDetached()))warn(WarningType::DelayedDetach, EmittingClass::QCharRef);
#endifs.detach();}s.d->data()[i] = c.unicode();return *this;
}

我们看到上面源码中if (Q_UNLIKELY(i >= s.d->size))判断下标有没有超出字符串大小,如果超出了,则需要调用resize重新开辟一块内存,如果没有超出,则调用detach()来分离数据,在分离的时候会判断当前引用计数,如果计数大于1,则会创建新的副本数据进行修改。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/41692.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

动态颤抖的眼睛效果404页面源码

动态颤抖的眼睛效果404页面源码, 源码由HTMLCSSJS组成,记事本打开源码文件可以进行内容文字之类的修改,双击html文件可以本地运行效果,也可以上传到服务器里面,重定向这个界面 动态颤抖的眼睛效果404页面源码

springboot+vue+mybatis图书馆借阅管理系统+PPT+论文+讲解+售后

21世纪的今天,随着社会的不断发展与进步,人们对于信息科学化的认识,已由低层次向高层次发展,由原来的感性认识向理性认识提高,管理工作的重要性已逐渐被人们所认识,科学化的管理,使信息存储达到…

python 将stl数据转为vtk

在Python中,可以使用vtk库将STL(Stereolithography)三维模型数据转换为VTK(Visualization Toolkit)格式。以下是一个简单的例子,演示如何进行转换: 首先,确保安装了vtk库。如果没有…

AI大模型时代的存储发展趋势

从2022年下半年,大模型和AIGC这两个词变得极其火热,而GPU的市场也是一卡难求。对于这种迷乱和火热,让我想起了当年的比特币挖矿和IPFS。似乎世界一年一个新风口,比特币、元宇宙、NFT、AIGC,金钱永不眠,IT炒…

IIS数字功放MAX98357开发板/评估系统

前言 MAX98357中文介绍请访问下行链接 MAX98357、MAX98357A、MAX98357B小巧、低成本、PCM D类IIS放大器,具有AB类性能中文说明规格书 一般描述 MAX98357 开发板(DEV 板)是一个完全组装并经过测试的 PCB,用于评估 MAX98357 I2S …

对象存储服务的完整性检查

使用场景有: 上传对象后,如何确定对象存储收到的数据和客户端本地的数据是否一致。下载对象后,如何确定本地收到的数据和对象存储保存的数据是否一致。 AWS S3 Checking object integrity 实现完整性校验时,AWS S3提供的算法包…

如何在Spring Boot中使用Quartz调度任务

如何在Spring Boot中使用Quartz调度任务 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将深入探讨如何在Spring Boot应用程序中集成和使用Quartz调度任…

C++怎么解决不支持字符串枚举?

首先,有两种方法:使用命名空间和字符串常量与使用 enum class 和辅助函数。 表格直观展示 特性使用命名空间和字符串常量使用 enum class 和辅助函数类型安全性低 - 编译器无法检查字符串有效性,运行时发现错误高 - 编译期类型检查&#xf…

2024 年 6 月区块链游戏研报:Pixels 引发 DAU 波动,行业用户留存率差异显著

作者:Stella L (stellafootprint.network) 数据来源:区块链游戏研究页面 2024 年 6 月,加密货币市场遭遇显著回调,比特币跌幅达 7.3%,以太坊更是下跌了 9.8%。此番波动不可避免地波及区块链游戏领域,导致…

Hudi 写入流程(图)

前言 主要为之前总结的源码文章补充流程图。总结一下整体流程说明 之前以Java Client为例,总结了 Insert 源码的整体流程及部分源码,由于各种原因,没有总结完。长时间不看这方面的源码,容易忘记,之前没有总结流程图,现在回忆起来比较麻烦,不如看流程图方便快捷。所以先补…

2024亚太杯中文赛B题洪水灾害的数据分析与预测原创论文分享

大家好,从昨天肝到现在,终于完成了2024年第十四届 APMCM 亚太地区大学生数学建模竞赛B题洪水灾害的数据分析与预测的完整论文啦。 实在精力有限,具体的讲解大家可以去讲解视频: 2024亚太杯中文赛B题洪水灾害预测原创论文保姆级教…

2024/7/6 英语每日一段

More than half of late-teens are specifically calling for more youth work that offers “fun”, with older teenagers particularly hankering for more jollity, according to a study carried out by the National Youth Agency. One in 10 said they have zero option…

量化机器人:金融市场的智能助手

引言 想象一下,在繁忙的金融市场中,有一位不知疲倦、冷静客观的“超级交易员”,它能够迅速分析海量数据,精准捕捉交易机会,并自动完成买卖操作。这位“超级交易员”不是人类,而是我们今天要聊的主角——量…

数据库——锁

title: 数据库——锁 date: 2024-07-06 12:25:15 tags: 数据库 categories: 数据库 cover: /image/T2.jpg description: 数据库里对锁的应用,锁的一些相关知识 锁 在数据库管理和并发编程中,锁(Locks)是一种重要的同步机制&…

Vue 3 中集成 ECharts(附一些案例)

Vue 3 中集成 ECharts 的完全指南 引言 在现代Web开发中,Vue 3以其卓越的性能和灵活的Composition API赢得了广泛的关注。而ECharts,作为开源的一个使用JavaScript实现的强大可视化库,以其丰富的图表类型和高度可定制性成为了数据可视化的首…

计算机的错误计算(二十二)

摘要 计算机的错误计算(十九)展示了计算机的一个错误计算:本应该为 0的算式的结果不为0. 那么,增加计算精度,能确定是0吗?不一定。 计算机的错误计算(十九)展示了计算机对 的错误计…

适用于 Windows的 5 个最佳 PDF 转 Word 转换器

PDF 文件是共享文档的首选格式,但是,此类文件存在限制,使其难以修改或编辑。因此,您可能会发现自己正在寻找一种将 PDF 文件转换为 Word 或其他可编辑格式的方法。 有许多不同的 PDF 转换器,每个转换器的功能略有不同…

vue require引入静态文件报错

如果是通过向后端发送请求,动态的获取对应的文件数据流很容易做到文件的显示和加载。现在研究,一些不存放在后端而直接存放在vue前端项目中的静态媒体文件如何加载。 通常情况下,vue项目的图片jpg,png等都可以直接在/ass…

Perl 语言入门学习及实践

一、Perl 语言简介 Perl,全称为“Practical Extraction and Reporting Language”,是一种功能强大的脚本语言,广泛应用于文本处理、系统管理、网络编程和Web开发等领域。其丰富的库支持和正则表达式能力,使得Perl成为数据挖掘、日…

hmmer数据库合并

下载的数据库,解压之后是一个很多hmm文件的文件夹,不便于注释 https://fileshare.csb.univie.ac.at/vog/vog224/vfam.hmm.tar.gz cat *.hmm > vog224.hmm hmmpress vog224.hmm比对 hmmscan --tblout test_VOG.tbl --domtblout test_VOG.dom --noal…