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 takes place behind the scenes; the programmer does not need to worry about it. Even 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 total control of its internal data. In any member functions that modify its data, it automatically detaches before modifying the data.
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
,因為描繪像素圖會修改它。
警告: Do not copy an implicitly shared container ( QMap , QVector , etc.) while you are iterating over it using an non-const STL-style iterator.
| OpenGL | QGLColormap class is used for installing custom colormaps into a QGLWidget |
| QBitArray | 位數組 |
| QBitmap | 單色 (1 位深度) 像素圖 |
| QBrush | 定義 QPainter 繪製形狀的填充圖案 |
| QByteArray | 字節數組 |
| QCache | 提供緩存的模闆類 |
| QContiguousCache | 提供連續緩存的模闆類 |
| QCursor | 具有任意形狀的鼠標光標 |
| QDir | 訪問目錄結構及其內容 |
| QFileInfo | 與係統無關的文件信息 |
| QFont | Specifies a font used for drawing text |
| QFontInfo | 有關字體的一般信息 |
| QFontMetrics | 字體規格信息 |
| QFontMetricsF | 字體規格信息 |
| QGradient | 用於組閤 QBrush 以指定漸變填充 |
| QHash | 提供基於哈希錶的字典的模闆類 |
| QIcon | 在不同模式和狀態下的可伸縮圖標 |
| QImage | 獨立於硬件的圖像錶示 (允許直接訪問像素數據,且可以被用作描繪設備) |
| QKeySequence | 封裝作為快捷鍵使用的鍵序列 |
| QLinkedList | 提供鏈接列錶的模闆類 |
| QList | 提供列錶的模闆類 |
| QLocale | 在數字及其各種語言的字符串錶示之間轉換 |
| QMap | Template class that provides a skip-list-based dictionary |
| QMultiHash | 提供多值哈希的方便 QHash 子類 |
| QMultiMap | 提供多值映射的方便 QMap 子類 |
| QPainterPath | 用於描繪操作的容器,使圖形形狀能夠被構造和重用 |
| QPalette | 包含各 Widget 狀態的顔色組 |
| QPen | 定義 QPainter 如何繪製綫條和形狀的輪廓 |
| QPicture | 用於記錄和重演 QPainter 命令的描繪設備 |
| QPixmap | 可以用作描繪設備的離屏圖像錶示 |
| QPolygon | 使用整數精度的點嚮量 |
| QPolygonF | 使用浮點精度的點嚮量 |
| QQueue | 提供隊列的通用容器 |
| QRegExp | 使用正則錶達式進行模式匹配 |
| QRegion | 為描繪器指定裁剪區域 |
| QSet | 提供基於哈希錶的集的模闆類 |
| QSqlField | 操縱 SQL 數據庫錶和視圖中的字段 |
| QSqlQuery | 執行和操縱 SQL 語句的手段 |
| QSqlRecord | 封裝數據庫記錄 |
| QStack | 提供堆棧的模闆類 |
| QString | Unicode 字符串 |
| QStringList | 字符串列錶 |
| QTextBoundaryFinder | 在字符串中查找 Unicode 文本邊界的辦法 |
| QTextCursor | 提供訪問和修改 QTextDocument 的 API |
| QTextDocumentFragment | 錶示一塊來自 QTextDocument 的格式化文本 |
| QTextFormat | 用於 QTextDocument 的格式化信息 |
| QUrl | 用於操控 URL 的方便接口 |
| QVariant | 舉動像最常見 Qt 數據類型的並集 |
| QVector | 提供動態數組的模闆類 |
| QX11Info | Information about the X display configuration |