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 value semantics )。
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 | Vector of points using integer precision |
| QPolygonF | Vector of points using floating point precision |
| 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 |