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, QVector, etc.) while you use STL-style iterator. See Implicit sharing iterator problem.

QDebug

Output stream for debugging information

QDir

Access to directory structures and their contents

QFileInfo

System-independent file information

QProcessEnvironment

Holds the environment variables that can be passed to a program

QStorageInfo

Provides information about currently mounted storage and drives

QUrl

Convenient interface for working with URLs

QUrlQuery

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

QPersistentModelIndex

Used to locate data in a data model

QJsonArray

Encapsulates a JSON array

QJsonDocument

Way to read and write JSON documents

QJsonParseError

Used to report errors during JSON parsing

QJsonObject

Encapsulates a JSON object

QJsonValue

Encapsulates a value in JSON

QVariant

Acts like a union for the most common Qt data types

QMimeType

Describes types of file or data, represented by a MIME type string

QBitArray

Array of bits

QByteArray

Array of bytes

QByteArrayList

List of byte arrays

QCache

Template class that provides a cache

QCollator

Compares strings according to a localized collation algorithm

QCollatorSortKey

Can be used to speed up string collation

QCommandLineOption

Defines a possible command-line option

QContiguousCache

Template class that provides a contiguous cache

QDateTime

Date and time functions

QHash

Template class that provides a hash-table-based dictionary

QMultiHash

Convenience QHash subclass that provides multi-valued hashes

QLinkedList

Template class that provides linked lists

QList

Template class that provides lists

QLocale

Converts between numbers and their string representations in various languages

QMap

Template class that provides a red-black-tree-based dictionary

QMultiMap

Convenience QMap subclass that provides multi-valued maps

QQueue

Generic container that provides a queue

QRegExp

Pattern matching using regular expressions

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

QStack

Template class that provides a stack

QString

Unicode character string

QStringList

List of strings

QTextBoundaryFinder

Way of finding Unicode text boundaries in a string

QVector

Template class that provides a dynamic array

QDBusPendingCall

Refers to one pending asynchronous call

QDBusUnixFileDescriptor

Holds one Unix file descriptor

QBitmap

Monochrome (1-bit depth) pixmaps

QIcon

Scalable icons in different modes and states

QImage

Hardware-independent image representation that allows direct access to the pixel data, and can be used as a paint device

QPicture

Paint device that records and replays QPainter commands

QPixmap

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

QCursor

Mouse cursor with an arbitrary shape

QKeySequence

Encapsulates a key sequence as used by shortcuts

QPalette

Contains color groups for each widget state

QOpenGLDebugMessage

Wraps an OpenGL debug message

QBrush

Defines the fill pattern of shapes drawn by QPainter

QGradient

Used in combination with QBrush to specify gradient fills

QPainterPath

Container for painting operations, enabling graphical shapes to be constructed and reused

QPen

Defines how a QPainter should draw lines and outlines of shapes

QPolygon

Vector of points using integer precision

QPolygonF

Vector of points using floating point precision

QRegion

Specifies a clip region for a painter

QFont

Specifies a font used for drawing text

QFontInfo

General information about fonts

QFontMetrics

Font metrics information

QFontMetricsF

Font metrics information

QGlyphRun

Direct access to the internal glyphs in a font

QRawFont

Access to a single physical instance of a font

QStaticText

Enables optimized drawing of text when the text and its layout is updated rarely

QTextCursor

Offers an API to access and modify QTextDocuments

QTextDocumentFragment

Represents a piece of formatted text from a QTextDocument

QTextBlockFormat

Formatting information for blocks of text in a QTextDocument

QTextCharFormat

Formatting information for characters in a QTextDocument

QTextFormat

Formatting information for a QTextDocument

QTextFrameFormat

Formatting information for frames in a QTextDocument

QTextImageFormat

Formatting information for images in a QTextDocument

QTextListFormat

Formatting information for lists in a QTextDocument

QTextTableCellFormat

Formatting information for table cells in a QTextDocument

QTextTableFormat

Formatting information for tables in a QTextDocument

QNetworkCacheMetaData

Cache information

QHttpPart

Holds a body part to be used inside a HTTP multipart MIME message

QNetworkCookie

Holds one network cookie

QNetworkRequest

Holds a request to be sent with QNetworkAccessManager

QNetworkConfiguration

Abstraction of one or more access point configurations

QDnsDomainNameRecord

Stores information about a domain name record

QDnsHostAddressRecord

Stores information about a host address record

QDnsMailExchangeRecord

Stores information about a DNS MX record

QDnsServiceRecord

Stores information about a DNS SRV record

QDnsTextRecord

Stores information about a DNS TXT record

QNetworkAddressEntry

Stores one IP address supported by a network interface, along with its associated netmask and broadcast address

QNetworkInterface

Listing of the host's IP addresses and network interfaces

QNetworkProxy

Network layer proxy

QNetworkProxyQuery

Used to query the proxy settings for a socket

QSslCertificate

Convenient API for an X509 certificate

QSslCertificateExtension

API for accessing the extensions of an X509 certificate

QSslCipher

Represents an SSL cryptographic cipher

QSslConfiguration

Holds the configuration and state of an SSL connection

QSslError

SSL error

QSslKey

Interface for private and public keys

QSslPreSharedKeyAuthenticator

Authentication data for pre shared keys (PSK) ciphersuites