隱式共享

Qt 中的很多 C++ 類使用隱式數據共享,以最大化利用資源並最小化拷貝。隱式共享類既安全又高效當作為參數傳遞時,因為僅傳遞指嚮數據的指針,且僅當函數寫入時纔拷貝數據,即 寫入時拷貝 .

概述

共享類由指嚮包含引用計數和引用數據的共享數據塊的指針組成。

當創建共享對象時,它將引用計數設為 1。遞增引用計數,每當新對象引用共享數據時。和遞減引用計數,當對象解引用共享數據時。刪除共享數據,當引用計數變為 0 時。

When dealing with shared objects, there are two ways of copying an object. We usually speak about deep and shallow copies. A deep copy implies duplicating an object. A shallow copy is a reference copy, i.e. just a pointer to a shared data block. Making a deep copy can be expensive in terms of memory and CPU. Making a shallow copy is very fast, because it only involves setting a pointer and incrementing the reference count.

Object assignment (with operator=()) for implicitly shared objects is implemented using shallow copies.

The benefit of sharing is that a program does not need to duplicate data unnecessarily, which results in lower memory use and less copying of data. Objects can easily be assigned, sent as function arguments, and returned from functions.

Implicit sharing mostly takes place behind the scenes; the programmer rarely needs to worry about it. However, Qt's container iterators have different behavior than those from the STL. Read 隱式共享迭代器問題 .

In multithreaded applications, implicit sharing takes place, as explained in 綫程和隱式共享類 .

當實現自己的隱式共享類時,使用 QSharedData and QSharedDataPointer 類。

隱式共享細節

Implicit sharing automatically detaches the object from a shared block if the object is about to change and the reference count is greater than one. (This is often called 寫入時拷貝 or 值語義 )。

An implicitly shared class has control of its internal data. In any member functions that modify its data, it automatically detaches before modifying the data. Notice, however, the special case with container iterators; see 隱式共享迭代器問題 .

The QPen class, which uses implicit sharing, detaches from the shared data in all member functions that change the internal data.

代碼片段:

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
    }
}
					
					

類列錶

The classes listed below automatically detach from common data if an object is about to be changed. The programmer will not even notice that the objects are shared. Thus you should treat separate instances of them as separate objects. They will always behave as separate objects but with the added benefit of sharing data whenever possible. For this reason, you can pass instances of these classes as arguments to functions by value without concern for the copying overhead.

範例:

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 and p2 共享數據直到 QPainter::begin () 被調用對於 p2 ,因為描繪像素圖會修改它。

警告: 小心拷貝隱式共享容器 ( QMap , QVector ,等) 當使用 STL 樣式迭代器 。見 隱式共享迭代器問題 .

QBitArray

位數組

QBitmap

單色 (1 位深度) 像素圖

QBrush

定義 QPainter 繪製形狀的填充圖案

QByteArray

字節數組

QByteArrayList

字節數組列錶

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

字體規格信息

QGlyphRun

直接訪問字體中的內部字形

QGradient

用於組閤 QBrush 以指定漸變填充

QHash

提供基於哈希錶的字典的模闆類

QHostAddress

IP 地址

QHttp2Configuration

控製 HTTP/2 參數和設定

QHttpPart

保持本體部分 (要在 HTTP 多部分 MIME 消息內使用)

QIcon

在不同模式和狀態下的可伸縮圖標

QImage

獨立於硬件的圖像錶示 (允許直接訪問像素數據,且可以被用作描繪設備)

QJsonArray

封裝 JSON 數組

QJsonDocument

讀寫 JSON 文檔的辦法

QJsonObject

封裝 JSON 對象

QJsonParseError

用於在 JSON 剖析期間報告錯誤

QJsonValue

把值封裝在 JSON 中

QKeySequence

封裝作為快捷鍵使用的鍵序列

QList

提供列錶的模闆類

QLocale

在數字及其各種語言的字符串錶示之間轉換

QMap

提供基於紅-黑-樹的字典的模闆類

QMimeType

描述由 MIME 類型字符串錶示的文件或數據的類型

QMultiHash

提供多值哈希的方便 QHash 子類

QMultiMap

提供多值映射的方便 QMap 子類

QNetworkAddressEntry

存儲由網絡接口支持的一個 IP 地址及其關聯的 Netmask (網絡掩碼) 和廣播地址

QNetworkCacheMetaData

緩存信息

QNetworkCookie

保持一網絡 Cookie

QNetworkInterface

主機的 IP 地址和網絡接口列錶

QNetworkProxy

網絡層代理

QNetworkProxyQuery

用於查詢套接字的代理設置

QNetworkRequest

保持要采用 QNetworkAccessManager 發送的請求

QOpenGLDebugMessage

包裹 OpenGL 調試消息

QPainterPath

用於描繪操作的容器,使圖形形狀能夠被構造和重用

QPalette

包含各 Widget 狀態的顔色組

QPen

定義 QPainter 如何繪製綫條和形狀的輪廓

QPersistentModelIndex

用於在數據模型中定位數據

QPicture

用於記錄和重演 QPainter 命令的描繪設備

QPixmap

可以用作描繪設備的離屏圖像錶示

QPolygon

使用整數精度的點嚮量

QPolygonF

使用浮點精度的點嚮量

QProcessEnvironment

保持可以被傳遞給程序的環境變量

QQueue

提供隊列的通用容器

QRawFont

訪問字體的單物理實例

QRegExp

使用正則錶達式進行模式匹配

QRegion

為描繪器指定裁剪區域

QRegularExpression

使用正則錶達式進行模式匹配

QRegularExpressionMatch

QRegularExpression 針對字符串進行匹配的結果

QRegularExpressionMatchIterator

QRegularExpression 對象針對字符串的全局匹配結果迭代器

QSet

提供基於哈希錶的集的模闆類

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 數據類型的並集

QVector

提供動態數組的模闆類