隐式共享

Qt中的许多C++类使用隐式数据共享来最大化资源使用并最小化复制。隐式共享的类在作为参数传递时既安全又高效,因为只传递数据的指针,只有当函数写入数据时才复制数据,即写时复制

概述

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

当创建一个共享对象时,它将引用计数设置为1。每当一个新的对象引用共享数据时,引用计数递增,而当对象解除引用共享数据时递减。当引用计数变为零时,删除共享数据。

处理共享对象时,有两种复制对象的方式。我们通常会说关于深复制浅复制。深复制意味着复制一个对象。浅复制是一个引用复制,即仅指向共享数据块的指针。创建深复制在内存和CPU方面可能会很昂贵。创建浅复制非常快,因为它只涉及设置指针和递增引用计数。

对隐式共享对象的对象赋值(使用operator=())是通过浅复制实现的。

共享的好处是程序不需要不必要地复制数据,这导致了更低的内存使用和更少的复制。对象可以轻松赋值、作为函数的参数传递,并从函数中返回。

隐式共享通常在幕后发生;程序员很少需要担心这个问题。然而,Qt的容器迭代器与STL中的迭代器行为不同。请参阅隐式共享迭代器问题

在多线程应用程序中,隐式共享如线程和隐式共享类中所述。

在实现自己的隐式共享类时,请使用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 在对 p2 调用 QPainter::begin() 之前共享数据,因为绘制像素图会修改它。

警告:在使用 STL-style iterator 时,小心复制隐式共享的容器(例如,QMapQList等)。请参阅 隐式共享迭代器问题

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 记录的信息

QFileInfo

检索关于系统条目的信息

QFont

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

QFontInfo

关于字体的通用信息

QFontMetrics

字体度量信息

QFontMetricsF

字体度量信息

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

在请求或报告蓝牙低功耗连接参数更新时使用

QLowEnergyDescriptorData

用于创建 GATT 服务数据

QLowEnergyServiceData

用于设置 GATT 服务数据

QMap

提供关联数组模板类

QMimeType

使用 MIME 类型字符串描述文件或数据类型

QMqttTopicFilter

表示 MQTT 主题过滤器

QMqttTopicName

表示 MQTT 主题名称

QMultiHash

提供多值哈希的便捷 QHash 子类

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

指定 painter 的裁剪区域

QRegularExpression

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

QRegularExpressionMatch

将 QRegularExpression 用于字符串匹配的结果

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

Unicode字符字符串

QStringList

字符串列表

QTextBlockFormat

QTextDocument中文本块的格式化信息

QTextBoundaryFinder

在字符串中找到Unicode文本边界的途径

QTextCharFormat

QTextDocument中字符的格式化信息

QTextCursor

提供访问和修改QTextDocuments的API

QTextDocumentFragment

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

QTextFormat

QTextDocument的格式化信息

QTextFrameFormat

QTextDocument中框架的格式化信息

QTextImageFormat

QTextDocument中图像的格式化信息

QTextListFormat

QTextDocument中列表的格式化信息

QTextTableCellFormat

QTextDocument中表格单元格的格式化信息

QTextTableFormat

QTextDocument中表格的格式化信息

QUrl

用于处理URL的便捷界面

QUrlQuery

操纵URL查询中的键值对的途径

QVariant

作为最常见的Qt数据类型的联合

© 2024 Qt公司有限公司。此文档包含的贡献内容归其各自所有者的版权所有。本提供的文档是在自由软件基金会发布的GNU自由文档许可1.3版本下授权的。http://www.gnu.org/licenses/fdl.html Qt和相应的标志是芬兰及其它国家的Qt公司商标。所有其他商标是其各自所有者的财产。