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 樣式迭代器 。見 隱式共享迭代器問題 .
| 位數組 | |
| 單色 (1 位深度) 像素圖 | |
| 定義 QPainter 繪製形狀的填充圖案 | |
| 字節數組 | |
| 字節數組列錶 | |
| 提供緩存的模闆類 | |
| 根據本地整理算法比較字符串 | |
| 可以用於加速字符串整理 | |
| 定義可能的命令行選項 | |
| 提供連續緩存的模闆類 | |
| 具有任意形狀的鼠標光標 | |
| 引用一待決異步調用 | |
| 保持一 Unix 文件描述符 | |
| 日期和時間功能 | |
| 調試信息輸齣流 | |
| 訪問目錄結構及其內容 | |
| 存儲域名記錄的有關信息 | |
| 存儲有關主機地址記錄的信息 | |
| 存儲有關 DNS MX 記錄的信息 | |
| 存儲有關 DNS SRV 記錄的信息 | |
| 存儲有關 DNS TXT 記錄的信息 | |
| 與係統無關的文件信息 | |
| 指定用於繪製文本的字體查詢 | |
| 有關字體的一般信息 | |
| 字體規格信息 | |
| 字體規格信息 | |
| 直接訪問字體中的內部字形 | |
| 用於組閤 QBrush 以指定漸變填充 | |
| 提供基於哈希錶的字典的模闆類 | |
| IP 地址 | |
| 控製 HTTP/2 參數和設定 | |
| 保持本體部分 (要在 HTTP 多部分 MIME 消息內使用) | |
| 在不同模式和狀態下的可伸縮圖標 | |
| 獨立於硬件的圖像錶示 (允許直接訪問像素數據,且可以被用作描繪設備) | |
| 封裝 JSON 數組 | |
| 讀寫 JSON 文檔的辦法 | |
| 封裝 JSON 對象 | |
| 用於在 JSON 剖析期間報告錯誤 | |
| 把值封裝在 JSON 中 | |
| 封裝作為快捷鍵使用的鍵序列 | |
| 提供列錶的模闆類 | |
| 在數字及其各種語言的字符串錶示之間轉換 | |
| 提供基於紅-黑-樹的字典的模闆類 | |
| 描述由 MIME 類型字符串錶示的文件或數據的類型 | |
| 提供多值哈希的方便 QHash 子類 | |
| 提供多值映射的方便 QMap 子類 | |
| 存儲由網絡接口支持的一個 IP 地址及其關聯的 Netmask (網絡掩碼) 和廣播地址 | |
| 緩存信息 | |
| 保持一網絡 Cookie | |
| 主機的 IP 地址和網絡接口列錶 | |
| 網絡層代理 | |
| 用於查詢套接字的代理設置 | |
| 保持要采用 QNetworkAccessManager 發送的請求 | |
| 包裹 OpenGL 調試消息 | |
| 用於描繪操作的容器,使圖形形狀能夠被構造和重用 | |
| 包含各 Widget 狀態的顔色組 | |
| 定義 QPainter 如何繪製綫條和形狀的輪廓 | |
| 用於在數據模型中定位數據 | |
| 用於記錄和重演 QPainter 命令的描繪設備 | |
| 可以用作描繪設備的離屏圖像錶示 | |
| 使用整數精度的點嚮量 | |
| 使用浮點精度的點嚮量 | |
| 保持可以被傳遞給程序的環境變量 | |
| 提供隊列的通用容器 | |
| 訪問字體的單物理實例 | |
| 使用正則錶達式進行模式匹配 | |
| 為描繪器指定裁剪區域 | |
| 使用正則錶達式進行模式匹配 | |
| QRegularExpression 針對字符串進行匹配的結果 | |
| QRegularExpression 對象針對字符串的全局匹配結果迭代器 | |
| 提供基於哈希錶的集的模闆類 | |
| 用於 X509 證書的便捷 API | |
| 用於訪問 X509 證書擴展名的 API | |
| 錶示 SSL 加密密碼 | |
| 保持 SSL 連接的配置和狀態 | |
| 用於服務器的 Diffie-Hellman 參數的接口 | |
| SSL 錯誤 | |
| 用於私鑰和公鑰的接口 | |
| 用於 PSK (預共享密鑰) 密碼套件的身份驗證數據 | |
| 提供堆棧的模闆類 | |
| 當文本及其布局很少更新時,啓用優化文本繪製 | |
| 提供有關當前掛載的存儲和驅動器的信息 | |
| Unicode 字符串 | |
| 字符串列錶 | |
| 用於 QTextDocument 文本塊的格式化信息 | |
| 在字符串中查找 Unicode 文本邊界的辦法 | |
| 用於 QTextDocument 字符的格式化信息 | |
| 提供訪問和修改 QTextDocument 的 API | |
| 錶示一塊來自 QTextDocument 的格式化文本 | |
| 用於 QTextDocument 的格式化信息 | |
| 用於 QTextDocument 框架的格式化信息 | |
| 用於 QTextDocument 圖像的格式化信息 | |
| 用於 QTextDocument 列錶的格式化信息 | |
| 用於 QTextDocument 中錶格單元格的格式化信息 | |
| 用於 QTextDocument 中錶格的格式化信息 | |
| 用於操控 URL 的方便接口 | |
| 在 URL 的查詢中操縱鍵/值對的方法 | |
| 舉動像最常見 Qt 數據類型的並集 | |
| 提供動態數組的模闆類 |