QT 隐式共享 Implicit Sharing

很多QT中的类都是隐式共享的,它在作为参数传递时既安全又有效率。

上一讲中提到了一个implicit sharing的问题,说QT容器类是隐式共享的。文档中讲了一个这样的问题:

一些Qt函数返回一个容器,如果想使用STL风格的迭代器遍历某函数的返回值,就必须复制此容器并且遍历这个副本,例如,下面的代码给出了如何遍历由QSplitter::sizes()返回的QList<int>的正确方式。

   // RIGHT

   const QList<int> sizes = splitter->sizes();

   QList<int>::const_iterator i;

   for (i = sizes.begin(); i != sizes.end(); ++i)

       ...

   

   // WRONG

   QList<int>::const_iterator i;

   for (i = splitter->sizes().begin();

           i != splitter->sizes().end(); ++i)

       ...

错误的原因是,每次调用QSplitter::sizes()都返回一个新的QList<int>值,如果不存储这个值,C++在开始迭代之前就会自动将其销毁,而只留下一个浮动迭代器。更糟的是,每次循环运行由于都调用了splitter->sizes().end()QSplitter::sizes()都必须生成一个新的列表的副本。总之,如果你使用STL风格迭代器,总是要在返回值的容器副本上进行遍历。而Java Style不需要,因为它自动生成了副本。

采用隐式共享,我们复制一个容器就像复制一个指针一样快。只有复制项之一发生改变时,数据才会实际被复制,而且这一切操作都可以在后台自动处理,由于这原因,隐式共享也叫“写时复制”。

隐式共享的优点是它是一个我们必须要考虑的最优化过程,它工作不需要我们干预,同时,隐式共享也提倡由值返回的对象的整洁编程风格。

很多类都是隐式共享的,除了容器类外还有QByteArray, QBrush, QFont, QPen, QImage, QPixmap, QString, QVariant 等等。

一个共享类对象创建,它的引用计数就记为1,如果将它传递给另一个对象,那计数就加1,并两个对象都指向内存中的相同的内部数据结构。如果某一个修改了对象值就会发生深度复制,以确保他们指向的数据结构不相同。并且之前的数据计数将减1,修改后的数据计数就为1。为1表示没有被共享。

这里简单讲下深度复制和浅度复制。

当处理一个共享对象时,我们有两种拷贝一个对象的方法:也就是我们常说的深度和浅度复制。深度复制是复制一个对象,浅度是复制一个对象引用,也就是说一个指针的共享数据块。显然使用浅度复制会很快。

隐式共享对象的复制操作符(operator=)是用浅度复制实现的。

当我们要实现自己的隐式共享类时,使用QSharedData, QSharedDataPointer类。

如果对象会改变或者引用计数是比另个更大,隐式共享就会自动从共享块中分离。一个隐式共享类完全控制它内部数据,如果任何成员函数修改了它的值,隐式共享都会在修改数据前自动分离。

例如QPen (它是隐式共享类),那些改变内部数据的所有成员函数分离共享数据:

   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

       }

   }

下面列出的类,如果一个对象被改变都会从共享数据中自动分离。编程者不需要注意这些类是共享的。因此要区别对待这些类的实例。这样,就可以作为参数传递这些实例而不关心复制代价了。

  例子:

     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 p2共享数据,直到为p2调用begin()

注意:你用non-const STL风格迭代器遍历容器(隐式共享容器,例如QMap,QVector等)时不需要复制容器。正如最开始讲的那个问题。

QBitmap

QIcon

QImage

QPicture

QPixmap

QCursor

QKeySequence

QPalette

QBrush

QGradient

QPainterPath

QPen

QPolygon

QPolygonF

QRegion

QFont

QFontInfo

QFontMetrics

QFontMetricsF

QGlyphRun

QRawFont

QStaticText

QTextCursor

QTextDocumentFragment

QTextBlockFormat

QTextCharFormat

QTextFormat

QTextFrameFormat

QTextImageFormat

QTextListFormat

QTextTableCellFormat

QTextTableFormat

QNetworkCacheMetaData

QHttpPart

QNetworkCookie

QNetworkRequest

QNetworkConfiguration

QDnsDomainNameRecord

QDnsHostAddressRecord

QDnsMailExchangeRecord

QDnsServiceRecord

QDnsTextRecord

QNetworkAddressEntry

QNetworkInterface

QNetworkProxy

QNetworkProxyQuery

QSslCertificate

QSslCertificateExtension

QSslCipher

QSslConfiguration

QSslError

QSslKey

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

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

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

QCache

Template class that provides a cache

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

你可能感兴趣的:(C++,C++,qt,qt,qt)