警告
本节包含从C++自动翻译到Python的代码片段,可能包含错误。
隐式共享¶
Qt中的许多C++类使用隐式数据共享来最大化资源使用并最小化复制。隐式共享类在作为参数传递时既安全又高效,因为只传递数据的指针,并且只有在函数写入数据时才会复制数据,即写时复制。
概述¶
共享类由一个指向共享数据块的指针组成,该数据块包含引用计数和数据。
当创建一个共享对象时,它会将引用计数设置为1。每当一个新对象引用共享数据时,引用计数会增加;当对象取消引用共享数据时,引用计数会减少。当引用计数变为零时,共享数据将被删除。
在处理共享对象时,有两种复制对象的方法。我们通常称之为深复制和浅复制。深复制意味着复制一个对象。浅复制是引用复制,即只是一个指向共享数据块的指针。在内存和CPU方面,进行深复制可能会很昂贵。进行浅复制非常快,因为它只涉及设置指针和增加引用计数。
隐式共享对象的对象赋值(使用operator=())是通过浅拷贝实现的。
共享的好处在于程序不需要不必要地复制数据,从而降低内存使用并减少数据复制。对象可以轻松地分配、作为函数参数传递,并从函数中返回。
隐式共享大多在幕后进行;程序员很少需要担心它。然而,Qt的容器迭代器与STL的迭代器行为不同。阅读隐式共享迭代器问题。
在多线程应用程序中,会发生隐式共享,如线程和隐式共享类中所述。
在实现您自己的隐式共享类时,请使用QSharedData
和QSharedDataPointer
类。
隐式共享详解¶
隐式共享会在对象即将更改且引用计数大于一时,自动将对象从共享块中分离。(这通常被称为写时复制或值语义。)
一个隐式共享类控制其内部数据。在任何修改其数据的成员函数中,它会在修改数据之前自动分离。然而,请注意容器迭代器的特殊情况;参见隐式共享迭代器问题。
QPen类使用隐式共享,在所有改变内部数据的成员函数中从共享数据中分离。
代码片段:
def setStyle(self, style): detach() # detach from common data d.style = style # set the style member def detach(self): if d.ref != 1: ... // perform a deep copy
班级列表¶
下面列出的类在对象即将更改时自动从公共数据中分离。程序员甚至不会注意到对象是共享的。因此,您应该将它们的不同实例视为不同的对象。它们将始终表现为不同的对象,但具有尽可能共享数据的额外好处。因此,您可以将这些类的实例作为参数按值传递给函数,而无需担心复制开销。
示例:
p1, = QPixmap() p1.load("image.bmp") p2 = p1 # p1 and p2 share data paint = QPainter() 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
等)时要小心。请参阅Implicit sharing iterator problem。
|
QDebug 类提供了一个用于调试信息的输出流。 |
QDir类提供了对目录结构及其内容的访问。 |
|
QFileInfo 类提供了一个与操作系统无关的 API,用于检索文件系统条目的信息。 |
|
QProcessEnvironment 类保存可以传递给程序的环境变量。 |
|
提供有关当前挂载的存储和驱动器的信息。 |
|
QUrl 类提供了一个方便的接口来处理 URL。 |
|
QUrlQuery 类提供了一种操作 URL 查询中键值对的方式。 |
|
QPersistentModelIndex 类用于在数据模型中定位数据。 |
|
|
QVariant 类充当最常见 Qt 数据类型的联合体。 |
QMimeType 类描述了文件或数据的类型,由 MIME 类型字符串表示。 |
|
QJsonArray 类封装了一个 JSON 数组。 |
|
QJsonDocument 类提供了一种读写 JSON 文档的方式。 |
|
|
QJsonObject 类封装了一个 JSON 对象。 |
QJsonParseError 类用于报告 JSON 解析期间的错误。 |
|
QJsonValue 类封装了 JSON 中的一个值。 |
|
QByteArray 类提供了一个字节数组。 |
|
|
QByteArrayList 类提供了一个字节数组的列表。 |
|
QByteArrayView 类提供了一个字节数组的视图,具有 QByteArray API 的只读子集。 |
QCollator 类根据本地化的排序算法比较字符串。 |
|
QCollatorSortKey 类可用于加速字符串排序。 |
|
QLocale 类在各种语言之间转换数字及其字符串表示形式。 |
|
QRegularExpression 类提供了使用正则表达式进行模式匹配的功能。 |
|
QRegularExpressionMatch 类提供了将 QRegularExpression 与字符串匹配的结果。 |
|
QRegularExpressionMatchIterator 类提供了一个迭代器,用于遍历 QRegularExpression 对象与字符串的全局匹配结果。 |
|
|
QString 类提供了一个 Unicode 字符字符串。 |
|
QStringList 类提供了一个字符串列表。 |
QTextBoundaryFinder 类提供了一种在字符串中查找 Unicode 文本边界的方法。 |
|
QDateTime 类提供了日期和时间功能。 |
|
QBitArray 类提供了一个位数组。 |
|
|
QCache 类是一个提供缓存的模板类。 |
QCommandLineOption 类定义了一个可能的命令行选项。 |
|
|
QContiguousCache 类是一个模板类,提供连续缓存。 |
|
QHash 类是一个模板类,提供基于哈希表的字典。 |
|
QMultiHash 类是一个方便的 QHash 子类,提供了多值哈希。 |
|
QList 类是一个提供动态数组的模板类。 |
|
QMap 类是一个模板类,提供了一个关联数组。 |
|
QMultiMap 类是一个模板类,它提供了一个具有多个等价键的关联数组。 |
|
QQueue 类是一个提供队列的通用容器。 |
|
QSet 类是一个模板类,提供了一个基于哈希表的集合。 |
|
QStack 类是一个提供堆栈的模板类。 |