隐式共享

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