Implicit Sharing

Many C++ classes in Qt use implicit data sharing to maximize resource usage and minimize copying. Implicitly shared classes are both safe and efficient when passed as arguments, because only a pointer to the data is passed around, and the data is copied only if and when a function writes to it, i.e., copy-on-write.

Overview

A shared class consists of a pointer to a shared data block that contains a reference count and the data.

When a shared object is created, it sets the reference count to 1. The reference count is incremented whenever a new object references the shared data, and decremented when the object dereferences the shared data. The shared data is deleted when the reference count becomes zero.

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 Implicit sharing iterator problem.

In multithreaded applications, implicit sharing takes place, as explained in Threads and Implicitly Shared Classes.

When implementing your own implicitly shared classes, use the QSharedData and QSharedDataPointer classes.

Implicit Sharing in Detail

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 copy-on-write or value semantics.)

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 Implicit sharing iterator problem.

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

Code fragment:

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

List of Classes

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.

Example:

 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();

In this example, p1 and p2 share data until QPainter::begin() is called for p2, because painting a pixmap will modify it.

Warning: Be careful with copying an implicitly shared container (QMap, QList, etc.) while you use STL-style iterator. See Implicit sharing iterator problem.

QBitmap

Monochrome (1-bit depth) pixmaps

QByteArrayList

List of byte arrays

QByteArrayView

View on an array of bytes with a read-only subset of the QByteArray API

QCache

Template class that provides a cache

QCommandLineOption

Defines a possible command-line option

QContiguousCache

Template class that provides a contiguous cache

QDebug

Output stream for debugging information

QGeoAreaMonitorInfo

Describes the parameters of an area or region to be monitored for proximity

QGeoPositionInfo

Contains information gathered on a global position, direction and velocity at a particular point in time

QGeoSatelliteInfo

Contains basic information about a satellite

QGlyphRun

Direct access to the internal glyphs in a font

QList

Template class that provides a dynamic array

QLocale

Converts between numbers and their string representations in various languages

QLowEnergyAdvertisingData

Represents the data to be broadcast during Bluetooth Low Energy advertising

QLowEnergyAdvertisingParameters

Represents the parameters used for Bluetooth Low Energy advertising

QLowEnergyCharacteristicData

Used to set up GATT service data

QLowEnergyConnectionParameters

Used when requesting or reporting an update of the parameters of a Bluetooth LE connection

QLowEnergyDescriptorData

Used to create GATT service data

QLowEnergyServiceData

Used to set up GATT service data

QMap

Template class that provides an associative array

QMqttTopicFilter

Represents a MQTT topic filter

QMqttTopicName

Represents a MQTT topic name

QMultiMap

Template class that provides an associative array with multiple equivalent keys

QPageRanges

Represents a collection of page ranges

QPen

Defines how a QPainter should draw lines and outlines of shapes

QPixmap

Off-screen image representation that can be used as a paint device

QQueue

Generic container that provides a queue

QRegularExpression

Pattern matching using regular expressions

QRegularExpressionMatch

The results of a matching a QRegularExpression against a string

QRegularExpressionMatchIterator

Iterator on the results of a global match of a QRegularExpression object against a string

QSet

Template class that provides a hash-table-based set

QSqlField

Manipulates the fields in SQL database tables and views

QSqlQuery

Means of executing and manipulating SQL statements

QSqlRecord

Encapsulates a database record

QSslCertificateExtension

API for accessing the extensions of an X509 certificate

QSslCipher

Represents an SSL cryptographic cipher

QSslPreSharedKeyAuthenticator

Authentication data for pre shared keys (PSK) ciphersuites

QStack

Template class that provides a stack

QStorageInfo

Provides information about currently mounted storage and drives

QUrlQuery

Way to manipulate a key-value pairs in a URL's query