隐式共享
Qt中的许多C++类使用隐式数据共享来最大化资源使用并最小化复制。隐式共享的类在作为参数传递时既安全又高效,因为只传递数据的指针,只有当函数写入数据时才复制数据,即写时复制。
概述
共享类由一个指向共享数据块的指针组成,该数据块包含引用计数和数据。
当创建一个共享对象时,它将引用计数设置为1。每当一个新的对象引用共享数据时,引用计数递增,而当对象解除引用共享数据时递减。当引用计数变为零时,删除共享数据。
处理共享对象时,有两种复制对象的方式。我们通常会说关于深复制和浅复制。深复制意味着复制一个对象。浅复制是一个引用复制,即仅指向共享数据块的指针。创建深复制在内存和CPU方面可能会很昂贵。创建浅复制非常快,因为它只涉及设置指针和递增引用计数。
对隐式共享对象的对象赋值(使用operator=())是通过浅复制实现的。
共享的好处是程序不需要不必要地复制数据,这导致了更低的内存使用和更少的复制。对象可以轻松赋值、作为函数的参数传递,并从函数中返回。
隐式共享通常在幕后发生;程序员很少需要担心这个问题。然而,Qt的容器迭代器与STL中的迭代器行为不同。请参阅隐式共享迭代器问题。
在多线程应用程序中,隐式共享如线程和隐式共享类中所述。
在实现自己的隐式共享类时,请使用QSharedData和QSharedDataPointer类。
隐式共享的详细情况
如果对象即将更改且引用计数大于1,隐式共享会自动从共享块中分离对象(这通常称为写时复制或值语义)。
隐式共享的类控制其内部数据。在所有修改其数据的成员函数中,它会自动在修改数据之前分离。但请注意,容器迭代器有特殊情况;请参阅隐式共享迭代器问题。
使用隐式共享的QPen类在所有修改内部数据的成员函数中都会从中断开与共享数据的连接。
代码片段
void QPen::setStyle(Qt::PenStyle style) { detach(); // detach from common data d->style = style; // set the style member } void QPen::detach() { if (d->ref != 1) { ... // perform a deep copy } }
类列表
以下列出的类在对象即将更改时将从通用数据中自动分离。程序员甚至不会注意到这些对象是共享的。因此,应将这些类的不同实例视为不同的对象。它们总是会作为独立对象行为,但只要可能,就会共享数据的额外好处。因此,可以无需担心复制开销,通过值将此类实例传递给函数作为参数。
示例
QPixmap p1, p2; p1.load("image.bmp"); p2 = p1; // p1 and p2 share data QPainter paint; paint.begin(&p2); // cuts p2 loose from p1 paint.drawText(0,50, "Hi"); paint.end();
在此示例中,p1
和 p2
在对 p2
调用 QPainter::begin() 之前共享数据,因为绘制像素图会修改它。
警告:在使用 STL-style iterator 时,小心复制隐式共享的容器(例如,QMap、QList等)。请参阅 隐式共享迭代器问题。
位数组 | |
单色(1位深度)像素图 | |
定义 QPainter 绘制形状的填充模式 | |
字节数组 | |
字节数组列表 | |
字节数组的只读视图,具有 QByteArray API 的读取子集 | |
一个提供缓存的模板类 | |
根据本地排序算法比较字符串 | |
可用于加快字符串排序 | |
定义可能的命令行选项 | |
提供一个连续缓存的模板类 | |
形状任意的鼠标光标 | |
指代一个挂起的异步调用 | |
持有一个 Unix 文件描述符 | |
日期和时间函数 | |
用于调试信息的输出流 | |
访问目录结构和它们的包含内容 | |
存储有关域名记录的信息 | |
存储有关主机地址记录的信息 | |
存储关于 DNS MX 记录的信息 | |
存储有关 DNS SRV 记录的信息 | |
存储有关 DNS TXT 记录的信息 | |
检索关于系统条目的信息 | |
指定用于绘制文本的字体查询 | |
关于字体的通用信息 | |
字体度量信息 | |
字体度量信息 | |
描述选中区域或区域监测的参数 | |
包含在特定时间点收集的全局位置、方向和速度信息 | |
包含有关卫星的基本信息 | |
直接访问字体内部的内部符号 | |
用于与 QBrush 结合以指定渐变填充 | |
提供一个基于散列表的字典的模板类 | |
IP 地址 | |
控制 HTTP/1 参数和设置 | |
控制 HTTP/2 参数和设置 | |
存储 HTTP 多部分 MIME 消息中要使用的主体部分 | |
在多种模式和状态下的可缩放图标 | |
无需硬件依赖的图像表示形式,允许直接访问像素数据,并可作为绘图设备使用 | |
封装 JSON 数组 | |
读取和写入 JSON 文档的途径 | |
封装 JSON 对象 | |
用于在 JSON 解析过程中报告错误 | |
封装 JSON 中的值 | |
将快捷键所使用的键序列封装 | |
提供链表模板类 | |
提供动态数组模板类 | |
将各种语言中的数字和它们的字符串表示进行转换 | |
表示在蓝牙低功耗广告期间要广播的数据 | |
表示蓝牙低功耗广告使用的参数 | |
用于设置 GATT 服务数据 | |
在请求或报告蓝牙低功耗连接参数更新时使用 | |
用于创建 GATT 服务数据 | |
用于设置 GATT 服务数据 | |
提供关联数组模板类 | |
使用 MIME 类型字符串描述文件或数据类型 | |
表示 MQTT 主题过滤器 | |
表示 MQTT 主题名称 | |
提供多值哈希的便捷 QHash 子类 | |
提供具有多个等效键的关联数组模板类 | |
存储网络接口支持的一个 IP 地址及其关联的子网掩码和广播地址 | |
缓存信息 | |
持有单个网络 Cookie | |
列出主机的 IP 地址和网络接口 | |
网络层代理 | |
用于查询套接字的代理设置 | |
持有要发送给 QNetworkAccessManager 的请求 | |
便捷类,用于分组具有共同网络请求属性的远程服务器端点 | |
封装 OpenGL 调试消息 | |
表示一组页面范围 | |
用于绘画操作的容器,可构建和重用图形形状 | |
包含每个小部件状态的调色板组 | |
定义 QPainter 应如何绘制形状的线条和轮廓 | |
用于在数据模型中定位数据 | |
记录并回放 QPainter 命令的绘图设备 | |
可用于作画设备的脱屏图像表示 | |
使用整数精度列出点 | |
使用浮点精度列出点 | |
持有可传递给程序的环境变量 | |
提供队列的通用容器 | |
访问字体单一生成实例 | |
使用正则表达式进行模式匹配 | |
指定 painter 的裁剪区域 | |
使用正则表达式进行模式匹配 | |
将 QRegularExpression 用于字符串匹配的结果 | |
在 QRegularExpression 对象全局匹配字符串的结果上的迭代器 | |
提供基于哈希表的集合模板类 | |
用于操作 SQL 数据库表和视图中的字段 | |
执行和操作 SQL 语句的手段 | |
封装数据库记录 | |
面向 X509 证书的便捷 API | |
访问 X509 证书扩展的 API | |
表示 SSL 密码学密文 | |
存储SSL连接的配置和状态 | |
服务器Diffie-Hellman参数的接口 | |
SSL错误 | |
私有和公钥的接口 | |
预共享密钥(PSK)加密套件的认证数据 | |
提供堆栈的模板类 | |
当文本及其布局不经常更新时,启用优化文本绘制 | |
提供关于当前挂载的存储和驱动器的信息 | |
Unicode字符字符串 | |
字符串列表 | |
QTextDocument中文本块的格式化信息 | |
在字符串中找到Unicode文本边界的途径 | |
QTextDocument中字符的格式化信息 | |
提供访问和修改QTextDocuments的API | |
代表来自QTextDocument的格式化文本片段 | |
QTextDocument的格式化信息 | |
QTextDocument中框架的格式化信息 | |
QTextDocument中图像的格式化信息 | |
QTextDocument中列表的格式化信息 | |
QTextDocument中表格单元格的格式化信息 | |
QTextDocument中表格的格式化信息 | |
用于处理URL的便捷界面 | |
操纵URL查询中的键值对的途径 | |
作为最常见的Qt数据类型的联合 |
© 2024 Qt公司有限公司。此文档包含的贡献内容归其各自所有者的版权所有。本提供的文档是在自由软件基金会发布的GNU自由文档许可1.3版本下授权的。http://www.gnu.org/licenses/fdl.html Qt和相应的标志是芬兰及其它国家的Qt公司商标。所有其他商标是其各自所有者的财产。