隐性共享
Qt 中的许多 C++ 类都使用隐式数据共享,以最大限度地提高资源利用率并减少复制。隐式共享类在作为参数传递时既安全又高效,因为只传递指向数据的指针,只有在函数写入数据时才复制数据,即写时复制。
概述
共享类由指向共享数据块的指针组成,共享数据块包含引用计数和数据。
每当有新对象引用共享数据时,引用计数就会递增,而当对象取消引用共享数据时,引用计数就会递减。当引用计数变为 0 时,共享数据将被删除。
在处理共享对象时,有两种复制对象的方法。我们通常说的是深拷贝和浅拷贝。深度拷贝意味着复制一个对象。浅层拷贝是引用拷贝,即只是指向共享数据块的指针。深度拷贝需要耗费大量内存和 CPU。浅层拷贝的速度非常快,因为它只需要设置一个指针并增加引用计数。
隐式共享对象的对象赋值(使用 operator=())就是通过浅层拷贝实现的。
共享的好处是,程序无需不必要地重复数据,从而减少了内存使用和数据复制。对象可以很容易地进行赋值、作为函数参数发送以及从函数中返回。
隐式共享大多发生在幕后,程序员很少需要担心。不过,Qt 的容器迭代器与 STL 的容器迭代器有着不同的行为。阅读隐式共享迭代器问题。
在多线程应用程序中,隐式共享会发生,详见《线程和隐式共享类》(Threads and Implicitly Shared Classes)。
在实现您自己的隐式共享类时,请使用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
共享数据,直到QPainter::begin() 被调用为p2
,因为绘制像素图会修改数据。
警告 在使用STL 样式的迭代器时,复制隐式共享容器(QMap,QList 等)时要小心。请参见隐式共享迭代器问题。
位数组 | |
单色(1 位深度)像素图 | |
定义 QPainter 绘制的图形的填充模式 | |
字节数组 | |
字节数组列表 | |
使用 QByteArray API 的只读子集查看字节数组 | |
提供缓存的模板类 | |
根据本地化整理算法比较字符串 | |
可用于加快字符串校对速度 | |
定义了一个可能的命令行选项 | |
提供连续缓存的模板类 | |
任意形状的鼠标指针 | |
指一个待处理的异步调用 | |
保存一个 Unix 文件描述符 | |
日期和时间功能 | |
用于调试信息的输出流 | |
访问目录结构及其内容 | |
存储域名记录信息 | |
存储主机地址记录信息 | |
存储有关 DNS MX 记录的信息 | |
存储有关 DNS SRV 记录的信息 | |
存储有关 DNS TXT 记录的信息 | |
存储有关 DNS TLSA 记录的信息 | |
检索文件系统条目信息的独立于操作系统的 API | |
指定查询用于绘制文本的字体 | |
有关字体的一般信息 | |
字体度量信息 | |
字体度量信息 | |
简化 QHttpMultiPart 对象构造的便利类 | |
简化 QHttpPart 对象构造的方便类 | |
描述要监控的区域的参数 | |
包含特定时间点收集的全球位置、方向和速度信息 | |
包含卫星的基本信息 | |
直接访问字体中的内部字形 | |
与 QBrush 结合使用,可指定渐变填充 | |
提供基于哈希表的字典的模板类 | |
IP 地址 | |
控制 HTTP/1 参数和设置 | |
控制 HTTP/2 参数和设置 | |
保存 HTTP 多部分 MIME 消息中使用的主体部分 | |
不同模式和状态下的可扩展图标 | |
独立于硬件的图像表示法,允许直接访问像素数据,并可用作绘画设备 | |
封装 JSON 数组 | |
读写 JSON 文档的方法 | |
封装一个 JSON 对象 | |
用于在 JSON 解析过程中报告错误 | |
封装 JSON 中的一个值 | |
封装快捷键使用的键序列 | |
提供链表的模板类 | |
提供动态数组的模板类 | |
在各种语言中转换数字及其字符串表示法 | |
代表蓝牙低功耗广告中要广播的数据 | |
代表用于蓝牙低功耗广告的参数 | |
用于设置 GATT 服务数据 | |
请求或报告蓝牙 LE 连接参数更新时使用 | |
用于创建 GATT 服务数据 | |
用于设置 GATT 服务数据 | |
提供关联数组的模板类 | |
描述文件或数据类型,用 MIME 类型字符串表示 | |
代表 MQTT 主题过滤器 | |
代表 MQTT 主题名称 | |
多值哈希表 | |
提供具有多个等价键的关联数组的模板类 | |
存储网络接口支持的一个 IP 地址及其相关的掩码和广播地址 | |
缓存信息 | |
保存一个网络 cookie | |
主机 IP 地址和网络接口列表 | |
网络层代理 | |
用于查询套接字的代理设置 | |
保存将通过 QNetworkAccessManager 发送的请求 | |
将共享共同网络请求属性的远程服务器端点分组的便利类 | |
封装 OpenGL 调试消息 | |
代表页面范围集合 | |
绘画操作容器,可构建和重复使用图形形状 | |
包含每个部件状态的颜色组 | |
定义 QPainter 应如何绘制线条和图形轮廓 | |
用于定位数据模型中的数据 | |
记录和重播 QPainter 命令的绘制设备 | |
可用作绘制设备的屏幕外图像表示法 | |
使用整数精度的点列表 | |
使用浮点精度的点列表 | |
保存可传递给程序的环境变量 | |
提供队列的通用容器 | |
访问字体的单个物理实例 | |
使用正则表达式进行模式匹配 | |
为绘制器指定剪辑区域 | |
使用正则表达式进行模式匹配 | |
正则表达式与字符串匹配的结果 | |
QRegularExpression 对象与字符串全局匹配结果的迭代器 | |
提供基于哈希表的集合的模板类 | |
操作 SQL 数据库表和视图中的字段 | |
执行和操作 SQL 语句的手段 | |
封装数据库记录 | |
X509 证书的便捷 API | |
访问 X509 证书扩展的 API | |
代表 SSL 加密密码 | |
保存 SSL 连接的配置和状态 | |
服务器 Diffie-Hellman 参数接口 | |
SSL 错误 | |
私钥和公钥接口 | |
预共享密钥(PSK)密码套件的验证数据 | |
提供堆栈的模板类 | |
当文本及其布局很少更新时,可优化文本绘制 | |
提供有关当前安装的存储和驱动器的信息 | |
统一字符编码字符串 | |
字符串列表 | |
QTextDocument 中文本块的格式化信息 | |
在字符串中查找 Unicode 文本边界的方法 | |
QTextDocument 中字符的格式化信息 | |
提供访问和修改 QTextDocument 的 API | |
代表来自 QTextDocument 的一段格式化文本 | |
QTextDocument 的格式化信息 | |
QTextDocument 中帧的格式化信息 | |
QTextDocument 中图像的格式化信息 | |
QTextDocument 中列表的格式设置信息 | |
QTextDocument 中表格单元格的格式设置信息 | |
QTextDocument 中表格的格式化信息 | |
处理 URL 的便捷界面 | |
操作 URL 查询中键值对的方法 | |
类似于最常见的 Qt 数据类型的联合体 |
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.