<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- /home/espenr/tmp/qt - 3.3.8 - espenr - 2499/qt - x11 - free - 3.3.8/doc/shclass.doc:36 -->
< html >
< head >
< meta http-equiv = "Content-Type" content = "text/html; charset=ISO-8859-1" >
< title > Shared Classes< / title >
< style type = "text/css" > < ! - -
fn { margin-left: 1cm; text-indent: -1cm; }
a:link { color: #004faf; text-decoration: none }
a:visited { color: #672967; text-decoration: none }
body { background: #ffffff; color: black; }
-->< / style >
< / head >
< body >
< table border = "0" cellpadding = "0" cellspacing = "0" width = "100%" >
< tr bgcolor = "#E5E5E5" >
< td valign = center >
< a href = "index.html" >
< font color = "#004faf" > Home< / font > < / a >
| < a href = "classes.html" >
< font color = "#004faf" > All Classes< / font > < / a >
| < a href = "mainclasses.html" >
< font color = "#004faf" > Main Classes< / font > < / a >
| < a href = "annotated.html" >
< font color = "#004faf" > Annotated< / font > < / a >
| < a href = "groups.html" >
< font color = "#004faf" > Grouped Classes< / font > < / a >
| < a href = "functions.html" >
< font color = "#004faf" > Functions< / font > < / a >
< / td >
< td align = "right" valign = "center" > < img src = "logo32.png" align = "right" width = "64" height = "32" border = "0" > < / td > < / tr > < / table > < h1 align = center > Shared Classes< / h1 >
< p > <!-- index reference counting --> < a name = "reference-counting" > < / a > <!-- index implicit sharing --> < a name = "implicit-sharing" > < / a > <!-- index explicit sharing --> < a name = "explicit-sharing" > < / a > <!-- index implicitly shared --> < a name = "implicitly-shared" > < / a > <!-- index explicitly shared --> < a name = "explicitly-shared" > < / a > <!-- index explicit sharing --> < a name = "explicit-sharing" > < / a > <!-- index shared implicitly --> < a name = "shared-implicitly" > < / a > <!-- index shared explicitly --> < a name = "shared-explicitly" > < / a >
< p > Many C++ classes in TQt use < em > explicit< / em > and < em > implicit< / em > data sharing
to maximize resource usage and minimize copying of data.
< p > <!-- toc -->
< ul >
< li > < a href = "#1" > Overview
< / a >
< li > < a href = "#2" > A TQByteArray Example
< / a >
< li > < a href = "#3" > Explicit vs. Implicit Sharing
< / a >
< li > < a href = "#4" > Explicitly Shared Classes
< / a >
< li > < a href = "#5" > Implicitly Shared Classes
< / a >
< li > < a href = "#6" > TQCString: implicit or explicit?
< / a >
< / ul >
<!-- endtoc -->
< p > < h2 > Overview
< / h2 >
< a name = "1" > < / a > < p > A shared class consists of a pointer to a shared data block that
contains a reference count and the data.
< p > 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.
< p > <!-- index deep copy --> < a name = "deep-copy" > < / a > <!-- index shallow copy --> < a name = "shallow-copy" > < / a >
< 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 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.
< p > Object assignment (with operator=()) for implicitly and explicitly
shared objects is implemented using shallow copies. A deep copy can be
made by calling a copy() function or by using < a href = "ntqdeepcopy.html" > TQDeepCopy< / a > .
< p > 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.
< p > Now comes the distinction between < em > explicit< / em > and < em > implicit< / em > sharing.
Explicit sharing means that the programmer must be aware of the fact
that objects share common data. Implicit sharing means that the
sharing mechanism takes place behind the scenes and the programmer
does not need to worry about it.
< p > < h2 > A < a href = "qbytearray.html" > TQByteArray< / a > Example
< / h2 >
< a name = "2" > < / a > < p > TQByteArray is an example of a shared class that uses explicit sharing.
Example:
< pre >
//Line a= b= c=
< a href = "qbytearray.html" > TQByteArray< / 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" > TQByteArray< / a > c = a; // 5: {12,56} {12,56} {12,56}
a.< a href = "ntqmemarray.html#detach" > detach< / a > (); // 6: {12,56} {12,56} {12,56}
a[1] = 78; // 7: {12,78} {12,56} {12,56}
b = a.< a href = "ntqmemarray.html#copy" > copy< / a > (); // 8: {12,78} {12,78} {12,56}
a[1] = 90; // 9: {12,90} {12,78} {12,56}
< / pre >
< p > The assignment < tt > a = b< / tt > on line 3 throws away < tt > a< / tt > 's original shared
block (the reference count becomes zero), sets < tt > a< / tt > 's shared block to
point to < tt > b< / tt > 's shared block and increments the reference count.
< p > On line 4, the contents of < tt > a< / tt > is modified. < tt > b< / tt > is also modified,
because < tt > a< / tt > and < tt > b< / tt > refer to the same data block. This is the
difference between explicit and implicit sharing (explained below).
< p > The < tt > a< / tt > object detaches from the common data on line 6. Detaching
means that the shared data is copied to make sure that an object has
its own private data. Therefore, modifying < tt > a< / tt > on line 7 does not
affect < tt > b< / tt > or < tt > c< / tt > .
< p > Finally, on line 8 we make a deep copy of < tt > a< / tt > and assign it to < tt > b< / tt > ,
so that when < tt > a< / tt > is modified on line 9, < tt > b< / tt > remains unchanged.
< p > < h2 > Explicit vs. Implicit Sharing
< / h2 >
< a name = "3" > < / a > < p > 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".) Explicit sharing
leaves this job to the programmer. If an explicitly shared object is
not detached, changing an object will change all other objects that
refer to the same data.
< p > Implicit sharing optimizes memory use and copying of data without
this side effect. So why didn't we implement implicit sharing for all
shared classes? The answer is that a class that allows direct access
to its internal data (for efficiency reasons), like < a href = "qbytearray.html" > TQByteArray< / a > , cannot
be implicitly shared, because it can be changed without letting
TQByteArray know.
< p > An implicitly shared class has total control of its internal data. In
any member functions that modify its data, it automatically detaches
before modifying the data.
< p > The < a href = "ntqpen.html" > TQPen< / a > class, which uses implicit sharing, detaches from the shared
data in all member functions that change the internal data.
< p > Code fragment:
< pre >
void TQPen::setStyle( PenStyle s )
{
detach(); // detach from common data
data-> style = s; // set the style member
}
void TQPen::detach()
{
if ( data-> count != 1 ) // only if > 1 reference
*this = copy();
}
< / pre >
< p > This is clearly not possible for TQByteArray, because the programmer
can do the following:
< p > < pre >
< a href = "qbytearray.html" > TQByteArray< / a > array( 10 );
array.< a href = "ntqmemarray.html#fill" > fill< / a > ( 'a' );
array[0] = 'f'; // will modify array
array.< a href = "ntqmemarray.html#data" > data< / a > ()[1] = 'i'; // will modify array
< / pre >
< p > If we monitor changes in a < a href = "qbytearray.html" > TQByteArray< / a > , the TQByteArray class would
become unacceptably slow.
< p > < h2 > Explicitly Shared Classes
< / h2 >
< a name = "4" > < / a > < p > All classes that are instances of the < a href = "ntqmemarray.html" > TQMemArray< / a > template class are
explicitly shared:
< p > < ul >
< li > < a href = "ntqbitarray.html" > TQBitArray< / a >
< li > < a href = "ntqpointarray.html" > TQPointArray< / a >
< li > < a href = "qbytearray.html" > TQByteArray< / a >
< li > Any other instantiation of < a href = "ntqmemarray.html" > TQMemArray< type> < / a >
< / ul >
< p > These classes have a detach() function that can be called if you want
your object to get a private copy of the shared data. They also have a
copy() function that returns a deep copy with a reference count of 1.
< p > The same is true for < a href = "tqimage.html" > TQImage< / a > , which does not inherit TQMemArray. < a href = "ntqmovie.html" > TQMovie< / a > is also explicitly shared, but it does not support detach() or
copy().
< p > < h2 > Implicitly Shared Classes
< / h2 >
< a name = "5" > < / a > < p > The TQt classes that are implicitly shared are:
< ul >
< li > < a href = "ntqbitmap.html" > TQBitmap< / a >
< li > < a href = "ntqbrush.html" > TQBrush< / a >
< li > < a href = "ntqcursor.html" > TQCursor< / a >
< li > < a href = "ntqfont.html" > TQFont< / a >
< li > < a href = "ntqfontinfo.html" > TQFontInfo< / a >
< li > < a href = "ntqfontmetrics.html" > TQFontMetrics< / a >
< li > < a href = "tqiconset.html" > TQIconSet< / a >
< li > < a href = "tqmap.html" > TQMap< / a >
< li > < a href = "ntqpalette.html" > TQPalette< / a >
< li > < a href = "ntqpen.html" > TQPen< / a >
< li > < a href = "ntqpicture.html" > TQPicture< / a >
< li > < a href = "ntqpixmap.html" > TQPixmap< / a >
< li > < a href = "ntqregion.html" > TQRegion< / a >
< li > < a href = "ntqregexp.html" > TQRegExp< / a >
< li > < a href = "tqstring.html" > TQString< / a >
< li > < a href = "tqstringlist.html" > TQStringList< / a >
< li > < a href = "tqvaluelist.html" > TQValueList< / a >
< li > < a href = "tqvaluestack.html" > TQValueStack< / a >
< / ul >
< p > These classes 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.
< p > Example:
< pre >
< a href = "ntqpixmap.html" > TQPixmap< / a > p1, p2;
p1.< a href = "ntqpixmap.html#load" > load< / a > ( "image.bmp" );
p2 = p1; // p1 and p2 share data
< a href = "ntqpainter.html" > TQPainter< / a > paint;
paint.< a href = "ntqpainter.html#begin" > begin< / a > ( & p2 ); // cuts p2 loose from p1
paint.< a href = "ntqpainter.html#drawText" > drawText< / a > ( 0,50, "Hi" );
paint.< a href = "ntqpainter.html#end" > end< / a > ();
< / pre >
< p > In this example, < tt > p1< / tt > and < tt > p2< / tt > share data until < a href = "ntqpainter.html#begin" > TQPainter::begin< / a > () is
called for < tt > p2< / tt > , because painting a pixmap will modify it. The same
also happens if anything is < a href = "tqimage.html#bitBlt" > bitBlt()< / a > 'ed into
< tt > p2< / tt > .
< p > < b > Warning:< / b > Do not copy an implicitly shared container (< a href = "tqmap.html" > TQMap< / a > ,
< a href = "tqvaluevector.html" > TQValueVector< / a > , etc.) while you are iterating over it.
< p > < h2 > TQCString: implicit or explicit?
< / h2 >
< a name = "6" > < / a > < p > < a href = "ntqcstring.html" > TQCString< / a > uses a mixture of implicit and explicit sharing. Functions
inherited from < a href = "qbytearray.html" > TQByteArray< / a > , such as data(), employ explicit sharing, while
those only in < a href = "ntqcstring.html" > TQCString< / a > detach automatically. Thus, TQCString is rather an
"experts only" class, provided mainly to ease porting from TQt 1.x to TQt 2.0.
We recommend that you use < a href = "tqstring.html" > TQString< / a > , a purely implicitly shared class.
< p >
<!-- eof -->
< p > < address > < hr > < div align = center >
< table width = 100% cellspacing = 0 border = 0 > < tr >
< td > Copyright © 2007
< a href = "troll.html" > Trolltech< / a > < td align = center > < a href = "trademarks.html" > Trademarks< / a >
< td align = right > < div align = right > TQt 3.3.8< / div >
< / table > < / div > < / address > < / body >
< / html >