Qt里面很多C++类都是采用隐式共享最大限度的提高资源利用率以及最新复制的原则。隐式共享数据作为参数时,不仅安全而且高效,因为传的是一个指针并且只有要修改这个数据时才会去拷贝,这里有个专业词汇copy-on-write在Qt官方提供的ppt中经常会出现这个词,说的就是隐式共享。
共享类(这个应该是指value type的类,学过Qt的都知道,Qt类可以分为两类,一个是identity type和value type)由一个共享数据块及指向这个块的计数器组成。
当共享对象被创建,这个块的计数器的值会被设置为1,并且当有新的对象指向共享数据库,那么他的计数器就会+1,当对象不指向这个内存块时,计数器会减少,当计数器为0时,这个共享块将会被删除。
当要对共享数据进行处理时,Qt有2种方式进行拷贝,也就是常说的深拷贝与浅拷贝。这里不再解释这2个拷贝了,这个隐式共享就和浅拷贝差不多,只不过是多了给增加了个引用计数器。
=这个操作一般是浅拷贝。
Qt的容器iterator和STL的不同,主要也是围绕隐式共享。如下代码:
#include
#include
int main(int argc, char *argv[])
{
QVector a, b;
a.resize(100000);
QVector::iterator i = a.begin();
b = a;
*i = 4;
a[0] = 5;
b.clear();
int j = *i;
qDebug() << "OVER";
}
下面最关键的来了,演示下上面所说的理论
这里可以看到当*i = 4还没执行的时候a中RefCount为2,也就是a,b都引用到了这个隐式内存中,所以为2。而这个i是直接指向了目前a最开始的那个内存。
下面看下一张图:
这里可以看到*i=4改变后,因为改变的是共享内存,所有a和b里面的数据都被改了。
最关键的地方来了,大家要注意,Qt最强大的机制之一copy-on-write来了。
这里a[0]=5,写及拷贝。a重新进行构造,现在RefCount又变成1了。
这个程序想表示的就是这个。也就是Qt很重要的运行机制。
还有给要提的就是这个i。
当b被clear后这个i就有问题,int j = i;这种操作很不安全。
当开发者需要写自己的隐式共享类时,使用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
}
}
当setStyle被调用后,这个set为设置,所以改变了,就会调用detach(),当d-ref不为1时,就会把所有数据拷贝一份。
下面是一些隐式共享的类,这里要记住,QTL的容器如果用STL风格去操作,需要考虑下隐式共享方面的问题。
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 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 |
QSslDiffieHellmanParameters |
Interface for Diffie-Hellman parameters for servers |
QSslError |
SSL error |
QSslKey |
Interface for private and public keys |
QSslPreSharedKeyAuthenticator |
Authentication data for pre shared keys (PSK) ciphersuites |