隐性共享

Qt 中的许多 C++ 类都使用隐式数据共享,以最大限度地提高资源利用率并减少复制。隐式共享类在作为参数传递时既安全又高效,因为只传递指向数据的指针,只有在函数写入数据时才复制数据,即时复制。

概述

共享类由指向共享数据块的指针组成,共享数据块包含引用计数和数据。

每当有新对象引用共享数据时,引用计数就会递增,而当对象取消引用共享数据时,引用计数就会递减。当引用计数变为 0 时,共享数据将被删除。

在处理共享对象时,有两种复制对象的方法。我们通常说的是拷贝和拷贝。深度拷贝意味着复制一个对象。浅层拷贝是引用拷贝,即只是指向共享数据块的指针。深度拷贝需要耗费大量内存和 CPU。浅层拷贝的速度非常快,因为它只需要设置一个指针并增加引用计数。

隐式共享对象的对象赋值(使用 operator=())就是通过浅层拷贝实现的。

共享的好处是,程序无需不必要地重复数据,从而减少了内存使用和数据复制。对象可以很容易地进行赋值、作为函数参数发送以及从函数中返回。

隐式共享大多发生在幕后,程序员很少需要担心。不过,Qt 的容器迭代器与 STL 的容器迭代器有着不同的行为。阅读隐式共享迭代器问题

在多线程应用程序中,隐式共享会发生,详见《线程和隐式共享类》(Threads and Implicitly Shared Classes)。

在实现您自己的隐式共享类时,请使用QSharedDataQSharedDataPointer 类。

隐式共享详解

如果对象即将发生变化且引用计数大于 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();

在本例中,p1p2 共享数据,直到QPainter::begin() 被调用为p2 ,因为绘制像素图会修改数据。

警告 在使用STL 样式的迭代器时,复制隐式共享容器(QMap,QList 等)时要小心。请参见隐式共享迭代器问题

QBitArray

位数组

QBitmap

单色(1 位深度)像素图

QBrush

定义 QPainter 绘制的图形的填充模式

QByteArray

字节数组

QByteArrayList

字节数组列表

QByteArrayView

使用 QByteArray API 的只读子集查看字节数组

QCache

提供缓存的模板类

QCollator

根据本地化整理算法比较字符串

QCollatorSortKey

可用于加快字符串校对速度

QCommandLineOption

定义了一个可能的命令行选项

QContiguousCache

提供连续缓存的模板类

QCursor

任意形状的鼠标指针

QDBusPendingCall

指一个待处理的异步调用

QDBusUnixFileDescriptor

保存一个 Unix 文件描述符

QDateTime

日期和时间功能

QDebug

用于调试信息的输出流

QDir

访问目录结构及其内容

QDnsDomainNameRecord

存储域名记录信息

QDnsHostAddressRecord

存储主机地址记录信息

QDnsMailExchangeRecord

存储有关 DNS MX 记录的信息

QDnsServiceRecord

存储有关 DNS SRV 记录的信息

QDnsTextRecord

存储有关 DNS TXT 记录的信息

QDnsTlsAssociationRecord

存储有关 DNS TLSA 记录的信息

QFileInfo

检索文件系统条目信息的独立于操作系统的 API

QFont

指定查询用于绘制文本的字体

QFontInfo

有关字体的一般信息

QFontMetrics

字体度量信息

QFontMetricsF

字体度量信息

QFormDataBuilder

简化 QHttpMultiPart 对象构造的便利类

QFormDataPartBuilder

简化 QHttpPart 对象构造的方便类

QGeoAreaMonitorInfo

描述要监控的区域的参数

QGeoPositionInfo

包含特定时间点收集的全球位置、方向和速度信息

QGeoSatelliteInfo

包含卫星的基本信息

QGlyphRun

直接访问字体中的内部字形

QGradient

与 QBrush 结合使用,可指定渐变填充

QHash

提供基于哈希表的字典的模板类

QHostAddress

IP 地址

QHttp1Configuration

控制 HTTP/1 参数和设置

QHttp2Configuration

控制 HTTP/2 参数和设置

QHttpPart

保存 HTTP 多部分 MIME 消息中使用的主体部分

QIcon

不同模式和状态下的可扩展图标

QImage

独立于硬件的图像表示法,允许直接访问像素数据,并可用作绘画设备

QJsonArray

封装 JSON 数组

QJsonDocument

读写 JSON 文档的方法

QJsonObject

封装一个 JSON 对象

QJsonParseError

用于在 JSON 解析过程中报告错误

QJsonValue

封装 JSON 中的一个值

QKeySequence

封装快捷键使用的键序列

QLinkedList

提供链表的模板类

QList

提供动态数组的模板类

QLocale

在各种语言中转换数字及其字符串表示法

QLowEnergyAdvertisingData

代表蓝牙低功耗广告中要广播的数据

QLowEnergyAdvertisingParameters

代表用于蓝牙低功耗广告的参数

QLowEnergyCharacteristicData

用于设置 GATT 服务数据

QLowEnergyConnectionParameters

请求或报告蓝牙 LE 连接参数更新时使用

QLowEnergyDescriptorData

用于创建 GATT 服务数据

QLowEnergyServiceData

用于设置 GATT 服务数据

QMap

提供关联数组的模板类

QMimeType

描述文件或数据类型,用 MIME 类型字符串表示

QMqttTopicFilter

代表 MQTT 主题过滤器

QMqttTopicName

代表 MQTT 主题名称

QMultiHash

多值哈希表

QMultiMap

提供具有多个等价键的关联数组的模板类

QNetworkAddressEntry

存储网络接口支持的一个 IP 地址及其相关的掩码和广播地址

QNetworkCacheMetaData

缓存信息

QNetworkCookie

保存一个网络 cookie

QNetworkInterface

主机 IP 地址和网络接口列表

QNetworkProxy

网络层代理

QNetworkProxyQuery

用于查询套接字的代理设置

QNetworkRequest

保存将通过 QNetworkAccessManager 发送的请求

QNetworkRequestFactory

将共享共同网络请求属性的远程服务器端点分组的便利类

QOpenGLDebugMessage

封装 OpenGL 调试消息

QPageRanges

代表页面范围集合

QPainterPath

绘画操作容器,可构建和重复使用图形形状

QPalette

包含每个部件状态的颜色组

QPen

定义 QPainter 应如何绘制线条和图形轮廓

QPersistentModelIndex

用于定位数据模型中的数据

QPicture

记录和重播 QPainter 命令的绘制设备

QPixmap

可用作绘制设备的屏幕外图像表示法

QPolygon

使用整数精度的点列表

QPolygonF

使用浮点精度的点列表

QProcessEnvironment

保存可传递给程序的环境变量

QQueue

提供队列的通用容器

QRawFont

访问字体的单个物理实例

QRegExp

使用正则表达式进行模式匹配

QRegion

为绘制器指定剪辑区域

QRegularExpression

使用正则表达式进行模式匹配

QRegularExpressionMatch

正则表达式与字符串匹配的结果

QRegularExpressionMatchIterator

QRegularExpression 对象与字符串全局匹配结果的迭代器

QSet

提供基于哈希表的集合的模板类

QSqlField

操作 SQL 数据库表和视图中的字段

QSqlQuery

执行和操作 SQL 语句的手段

QSqlRecord

封装数据库记录

QSslCertificate

X509 证书的便捷 API

QSslCertificateExtension

访问 X509 证书扩展的 API

QSslCipher

代表 SSL 加密密码

QSslConfiguration

保存 SSL 连接的配置和状态

QSslDiffieHellmanParameters

服务器 Diffie-Hellman 参数接口

QSslError

SSL 错误

QSslKey

私钥和公钥接口

QSslPreSharedKeyAuthenticator

预共享密钥(PSK)密码套件的验证数据

QStack

提供堆栈的模板类

QStaticText

当文本及其布局很少更新时,可优化文本绘制

QStorageInfo

提供有关当前安装的存储和驱动器的信息

QString

统一字符编码字符串

QStringList

字符串列表

QTextBlockFormat

QTextDocument 中文本块的格式化信息

QTextBoundaryFinder

在字符串中查找 Unicode 文本边界的方法

QTextCharFormat

QTextDocument 中字符的格式化信息

QTextCursor

提供访问和修改 QTextDocument 的 API

QTextDocumentFragment

代表来自 QTextDocument 的一段格式化文本

QTextFormat

QTextDocument 的格式化信息

QTextFrameFormat

QTextDocument 中帧的格式化信息

QTextImageFormat

QTextDocument 中图像的格式化信息

QTextListFormat

QTextDocument 中列表的格式设置信息

QTextTableCellFormat

QTextDocument 中表格单元格的格式设置信息

QTextTableFormat

QTextDocument 中表格的格式化信息

QUrl

处理 URL 的便捷界面

QUrlQuery

操作 URL 查询中键值对的方法

QVariant

类似于最常见的 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.