本页内容

隐式共享

Qt 中的许多 C++ 类都采用隐式数据共享机制,以最大限度地利用资源并减少复制操作。当作为参数传递时,隐式共享类既安全又高效,因为传递的只是数据的指针,只有当函数需要向数据写入时才会进行复制,即“写时复制”(copy-on-write)机制。

概述

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

创建共享对象时,会将引用计数设置为 1。每当有新对象引用该共享数据时,引用计数就会递增;当该对象解除对共享数据的引用时,引用计数就会递减。当引用计数变为零时,共享数据将被删除。

在处理共享对象时,有两种复制对象的方法。我们通常称之为深拷贝和浅拷贝。深拷贝意味着复制对象本身。 浅拷贝则是引用拷贝,即仅复制指向共享数据块的指针。进行深拷贝在内存和 CPU 消耗方面可能较为昂贵。而浅拷贝则非常快速,因为它仅涉及设置指针和递增引用计数。

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

共享的优势在于,程序无需不必要地复制数据,从而降低了内存占用并减少了数据复制操作。对象可以轻松地进行赋值、作为函数参数传递,以及从函数中返回。

隐式共享大多在后台进行;程序员很少需要担心它。然而,Qt 的容器迭代器与 STL 中的行为不同。请阅读《隐式共享迭代器问题》。

在多线程应用程序中,会发生隐式共享,具体说明请参阅《线程与隐式共享类》。

在实现自己的隐式共享类时,请使用QSharedData 和QSharedDataPointer 类。

隐式共享详解

如果对象即将发生变化且引用计数大于一,隐式共享会自动将该对象从共享块中分离出来。(这通常被称为“写时复制”或“值语义”。)

隐式共享类对其内部数据具有控制权。在任何会修改其数据的成员函数中,该类会在修改数据之前自动脱离共享块。但请注意容器迭代器的特殊情况;参见“隐式共享迭代器问题”。

QPen 类采用隐式共享机制,在所有会修改内部数据的成员函数中,都会与共享数据解除关联。

代码片段:

void QPen::setCapStyle(Qt::PenCapStyle c)
{
    if (d->capStyle == c)
        return;
    detach();
    d->capStyle = c;
}

void QPen::detach()
{
    d.detach();
}

类列表

如果某个对象即将被修改,下面列出的类会自动与共享数据脱离关联。 程序员甚至不会察觉到这些对象是共享的。因此,您应将它们的各个实例视为独立的对象。它们始终会表现为独立的对象,同时还能在可能的情况下共享数据。正因如此,您可以将这些类的实例作为按值传递的参数传给函数,而无需担心复制开销。

示例:

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 风格迭代器时,请 谨慎复制隐式共享的容器(如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

字体度量信息

QFontVariableAxis

表示字体中的一个可变轴

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

表示在蓝牙低功耗(BLE)广告期间要广播的数据

QLowEnergyAdvertisingParameters

表示用于蓝牙低功耗(BLE)广告的参数

QLowEnergyCharacteristicData

用于配置 GATT 服务数据

QLowEnergyConnectionParameters

用于请求或报告蓝牙低功耗连接参数的更新

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

表示一组页面范围

QPalette

包含每个控件状态对应的颜色组

QPen

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

QPersistentModelIndex

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

QPicture

用于记录和重放 QPainter 命令的绘制设备

QPixmap

可作为绘图设备的屏幕外图像表示

QPolygon

使用整数精度的点列表

QPolygonF

使用浮点精度表示的点列表

QProcessEnvironment

用于存储可传递给程序的环境变量

QQueue

提供队列功能的通用容器

QRawFont

访问字体的单个物理实例

QRegExp

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

QRegion

为绘图器指定剪切区域

QRegularExpression

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

QRegularExpressionMatch

将 QRegularExpression 与字符串进行匹配的结果

QRegularExpressionMatchIterator

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

QSet

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

QShader

包含已转换为多种着色语言的着色器的多个版本,以及反射元数据

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

Unicode字符串

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 数据类型的联合体

© 2026 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.