📄 shclass.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Qt Toolkit - Shared Classes</title><style type="text/css"><!--h3.fn,span.fn { margin-left: 1cm; text-indent: -1cm; }a:link { color: #004faf; text-decoration: none }a:visited { color: #672967; text-decoration: none }body { background: white; color: black; }--></style></head><body bgcolor="#ffffff"><p><table width="100%"><tr><td><a href="index.html"><img width="100" height="100" src="qtlogo.png"alt="Home" border="0"><img width="100"height="100" src="face.png" alt="Home" border="0"></a><td valign="top"><div align="right"><img src="dochead.png" width="472" height="27"><br><a href="classes.html"><b>Classes</b></a>- <a href="annotated.html">Annotated</a>- <a href="hierarchy.html">Tree</a>- <a href="functions.html">Functions</a>- <a href="index.html">Home</a>- <a href="topicals.html"><b>Structure</b> <font face="Arial,Helvetica,Geneva,Swiss,SunSans-Regular" align="center" size=32>Qte</font></a></div></table><h1 align="center"> Shared Classes</h1><br clear="all">Many C++ classes in Qt use data sharing mechanisms to maximizeresource usage and minimize copying of data. We use two mechanisms:explicit and implicit sharing.<p><h2>Overview</h2><p>A shared class consists of a pointer to a shared data block that contains<ul><li> A reference count.<li> The data.</ul><p>When a shared object is created, it sets the reference count to 1. Thereference count is incremented whenever a new object references the shareddata, and decremented when the object dereferences the shared data. Theshared data is deleted when the reference count becomes zero.<p>When dealing with shared objects, there are two ways of copying an object.We usually speak about <em>deep</em> and <em>shallow</em> copies. A deep copy impliesduplicating an object. A shallow copy is a reference copy, we only copy apointer to a shared data block. Making a deep copy can be expensive interms of memory and CPU. Making a shallow copy is very fast, because itonly involves setting a pointer and incrementing the reference count.<p>Object assignment (operator=) for all shared objects is implemented asshallow copies. A deep copy can be made by calling a copy() function.<p>The benefit of sharing is that a program does not need to duplicate datawhen it is not required, which results in less memory usage and lesscopying of data. Objects can easily be assigned, sent as functionarguments and returned from functions.<p>Qt implements two types of sharing: <em>explicit</em> and <em>implicit</em> sharing.Explicit sharing means that the programmer must be aware of the fact thatobjects share common data. Implicit sharing means that the sharingmechanism takes place behind the scenes and the programmer does not needto worry about it.<p><h2>A QByteArray Example</h2><p>QByteArray is an example of an shared class that uses explicit sharing.Example:<pre> // a= b= c= <a href="qbytearray.html">QByteArray</a> a(3),b(2) // 1) {?,?,?} {?,?} b[0] = 12; b[1] = 34; // 2) {?,?,?} {12,34} a = b; // 3) {12,34} {12,34} a[1] = 56; // 4) {12,56} {12,56} <a href="qbytearray.html">QByteArray</a> c = a; // 5) {12,56} {12,56} {12,56} a.<a href="qbytearray.html#57e5a9">detach</a>(); // 6) {12,56} {12,56} {12,56} a[1] = 78; // 7) {12,78} {12,56} {12,56} b = a.<a href="qbytearray.html#f38609">copy</a>(); // 8) {12,78} {12,78} {12,56} a[1] = 90; // 9) {12,90} {12,78} {12,56}</pre><p>The assignment <code>a = b</code> on line 3 throws away <code>a</code>'soriginal shared block (the reference count becomes zero), sets<code>a</code>'s shared block to point to <code>b</code>'s shared blockand increments the reference count.<p>On line 4, the contents of <code>a</code> is modified. <code>b</code> is also modified,because <code>a</code> and <code>b</code> refer the same data block. This is the differencebetween explicit and implicit sharing (explained below).<p>The <code>a</code> object detaches from the common data on line 6. Detaching meansto copy the shared data to make sure that an object has its own privatedata. Therefore, modifying <code>a</code> on line 7 will not affect <code>b</code> or <code>c.</code><p>Finally, on line 8 we make a deep copy of <code>a</code> and assign it to <code>b,</code>so that when <code>a</code> is modified on line 9, <code>b</code> remains unchanged.<p><h2>Explicit vs. Implicit Sharing</h2><p>The difference between explicit and implicit sharing is that implicitsharing automatically detaches the object from a shared block if theobject is about to change and the reference count is greater thanone. Explicit sharing leaves this job to the programmer. If an explicitlyshared object is not detached, changing this object will change all otherobjects that refer the same data.<p>Implicit sharing optimizes memory usage and copying of data without thisside-effect. Then, why didn't we implement implicit sharing for allshared classes? The answer is that a class that allows direct access toits internal data (for efficiency reasons), like QByteArray, cannot beimplicitly shared, because it can be changed without letting QByteArrayknow.<p>An implicitly shared class has total control of its internal data. In anymember function that modify its data, it automatically detaches beforemodifying the data.<p>The QPen class, which uses implicit sharing, detaches from the shared datain all member functions that change the internal data.<p>Code fragment:<pre> void QPen::setStyle( PenStyle s ) { detach(); // detach from common data data->style = s; // set the style member } void QPen::detach() { if ( data->count != 1 ) // only if >1 reference *this = copy(); }</pre><p>This is clearly not possible for QByteArray, because the programmer cando the following:<p><pre> <a href="qbytearray.html">QByteArray</a> array( 10 ); array.<a href="qbytearray.html#c8bd6a">fill</a>( 'a' ); array[0] = 'f'; // will modify array *( array.<a href="qbytearray.html#2733f4">data</a>() + 1 ) = 'i'; // will modify array</pre><p>If we should have monitored changes in a QByteArray, the QByteArray classwould be unacceptably slow.<p><h2>Explicitly Shared Classes</h2><p>All classes that are instances of the QArray template class are explicitlyshared:<ul><li><a href="qbitarray.html">QBitArray</a><li><a href="qpointarray.html">QPointArray</a><li><a href="qbytearray.html">QByteArray</a><li>Any other instantiation of <a href="qarray.html">QArray<type></a></ul><p>These classes have a detach() function that can be called if you want yourobject to get a private copy of the shared data. They also have a copy()function that returns a deep copy with reference count 1 of an object.<p>The same is true for <a href="qimage.html">QImage</a>, which does not inherit QArray. <a href="qmovie.html">QMovie</a>is also explicitly shared, but it does not support detach() and copy().<p><h2>Implicitly Shared Classes</h2><p>The Qt classes that are implicitly shared are:<ul><li><a href="qbitmap.html">QBitmap</a><li><a href="qbrush.html">QBrush</a><li><a href="qcursor.html">QCursor</a><li><a href="qfont.html">QFont</a><li><a href="qfontinfo.html">QFontInfo</a><li><a href="qfontmetrics.html">QFontMetrics</a><li><a href="qiconset.html">QIconSet</a><li><a href="qmap.html">QMap</a><li><a href="qpalette.html">QPalette</a><li><a href="qpen.html">QPen</a><li><a href="qpixmap.html">QPixmap</a><li><a href="qregion.html">QRegion</a><li><a href="qstring.html">QString</a><li><a href="qstringlist.html">QStringList</a><li><a href="qvaluelist.html">QValueList</a><li><a href="qvaluestack.html">QValueStack</a></ul><p>These classes automatically detach from common data if an object is aboutto be changed. The programmer will not even notice that the objects areshared. Thus you should treat separate instances of them as separateobjects. They will always behave as separate objects but with the addedbonus of sharing data whenever possible. For this reason, you can passthese classes as arguments to functions without having to think about thecopying overhead.<p>Example:<pre> <a href="qpixmap.html">QPixmap</a> p1, p2; p1.<a href="qpixmap.html#a728cf">load</a>( "image.bmp" ); p2 = p1; // p1 and p2 share data <a href="qpainter.html">QPainter</a> paint; paint.<a href="qpainter.html#02ed5d">begin</a>( &p2 ); // cuts p2 loose from p1 paint.<a href="qpainter.html#0f088f">drawText</a>( 0,50, "Hi" ); paint.<a href="qpainter.html#365784">end</a>();</pre><p>In this example, <code>p1</code> and <code>p2</code> share data until QPainter::begin() iscalled for <code>p2,</code> because painting a pixmap will modify it. The samehappens also if anything is <a href="qpaintdevice.html#35ae2e">bitBlt()</a>'ed into <code>p2.</code><p><h2>QCString - implicit or explicit?</h2><p><a href="qcstring.html">QCString</a> is a mixture of implicit and explicit sharing - functionsinherited from QByteArray, such as data(), employ explicit sharing, whilethose only in QCString detach automatically. Thus, QCString is somewhat an"expert only" class, provided mainly to ease porting from Qt 1.x to Qt 2.0.We recommend that you use <a href="qstring.html">QString</a>, a purely implicitly shared class.<p><address><hr><div align="center"><table width="100%" cellspacing="0" border="0"><tr><td>Copyright
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -