File: shclass.html

package info (click to toggle)
qt1g 1%3A1.45-1.1
  • links: PTS
  • area: non-free
  • in suites: potato
  • size: 17,436 kB
  • ctags: 20,174
  • sloc: cpp: 89,153; yacc: 1,273; ansic: 692; makefile: 479; lex: 326; sh: 150; perl: 94
file content (183 lines) | stat: -rw-r--r-- 8,186 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><html><head><meta name="robots" content="noindex"><title>Qt Shared Classes</title>
</head><body bgcolor="#ffffff">
<p>
<a href=index.html><img width=122 height=65 src=qtlogo.jpg alt="Qt logo" align=left border=0></a>
<center><img src=dochead.gif width=472 height=27></center>
<br clear=all>
<p>
<h1 align=center>Shared Classes</h1><br clear="all">
<p>
Many C++ classes in Qt utilize a data sharing mechanism to maximize
resource usage and minimize copying of data. We use two techniques:
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.  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>
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, we only copy 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 (operator=) for all shared objects is implemented as
shallow 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 data
when it is not required, which results in less memory usage and less
copying of data. Objects can easily be assigned, sent as function
arguments 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 that
objects share common data.  Implicite sharing means that the sharing
mechanism takes place behind the scenes and the programmer does not need
to worry about it.
<p>
<h2>A QString Example</h2>
<p>
QString is an example of an shared class that uses explicit sharing.
Example:
<pre>  <a href="qstring.html">QString</a> a = "one";    // 1)     a = "one"
  <a href="qstring.html">QString</a> b = "two";    // 2)     a = "one",    b = "two"
  a = b;                // 3)   a,b = "two"
  a[1] = 'a';           // 4)   a,b = "tao"
  <a href="qstring.html">QString</a> c = a;        // 5) a,b,c = "tao"
  a.<a href="qbytearray.html#b8">detach</a>();           // 6)     a = "tao"   b,c = "tao"
  a[1] = 'o';           // 7)     a = "too",  b,c = "tao"
  b = a.<a href="qstring.html#c6">copy</a>();         // 8)     a = "too",    b = "too",  c = "tao"
</pre>
<p>
The assignment <code>a = b</code> on line 3 throws away <code>a</code>'s
original shared block (the reference count becomes zero), sets
<code>a</code>'s shared block to point to <code>b</code>'s shared block
and 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 difference
between explicit and implicit sharing (explained below).
<p>
The <code>a</code> object detaches from the common data on line 6.  Detaching means
to copy the shared data to make sure that an object has its own private
data.  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>
<p>
<h2>Explicit vs. Implicit Sharing</h2>
<p>
The difference between explicit and implicit sharing is that 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. Explicit sharing leaves this job to the programmer.  If an explicitly
shared object is not detached, changing this object will change all other
objects that refer the same data.
<p>
Implicit sharing optimizes memory usage and copying of data without this
side-effect.  Then, why didn't we implement implicite sharing for all
shared classes?  The answer is that a class that allows direct access to
its internal data (for efficiency reasons), like QString, cannot be
implicitly shared, because it can be changed without letting QString know.
<p>
An implicitly shared class has total control of its internal data.  In any
member function that modify its data, it automatically detaches before
modifying the data.
<p>
The QPen class, which has implicit sharing, detaches from the shared data
in all member functions that change the internal data.
<p>
Code fragment:
<pre>  void QPen::setStyle( PenStyle s )
  {
      detach();                         // detach from common data
      data-&gt;style = s;                  // set the style member
  }

  void QPen::detach()
  {
      if ( data-&gt;count != 1 )           // only if &gt;1 reference
          *this = copy();
  }
</pre>
<p>
This is clearly not possible for QString, because the programmer can
do the following:
<p>
<pre>  <a href="qstring.html">QString</a> s = "test";
  s[0] = 'f';                           // will modify s
  *(s.<a href="qbytearray.html#b0">data</a>()+1) = 'i';                  // will modify s
</pre>
<p>
If we should have monitored changes in a QString, the QString class would
be unacceptably slow.
<p>
<h2>Explicitly Shared Classes</h2>
<p>
All classes that are instances of the QArray template class are explicitly
shared:
<ul>
<li><a href="qbitarray.html">QBitArray</a>
<li><a href="qbytearray.html">QByteArray</a>
<li><a href="qimage.html">QImage</a> (does not inherit QArray)
<li><a href="qpointarray.html">QPointArray</a>
<li><a href="qstring.html">QString</a>
<li>Any other instantiation of <a href="qarray.html">QArray&lt;type&gt;</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 reference count 1 of an object.
<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="qpen.html">QPen</a>
<li><a href="qpalette.html">QPalette</a>
<li><a href="qpixmap.html">QPixmap</a>
<li><a href="qregion.html">QRegion</a> (not fully implemented)
</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
bonus of sharing data whenever possible.  For this reason, you can pass
these classes as arguments to functions without having to think about the
copying overhead.
<p>
Example:
<pre>  <a href="qpixmap.html">QPixmap</a> p1, p2;
  p1.<a href="qpixmap.html#d4">load</a>( "image.bmp" );
  p2 = p1;                      // p1 and p2 share data
  <a href="qpainter.html">QPainter</a> paint;
  paint.<a href="qpainter.html#b0">begin</a>( &amp;p2 );           // cuts p2 loose from p1
  paint.<a href="qpainter.html#l4">drawText</a>( 0,50, "Hi" );
  paint.<a href="qpainter.html#b2">end</a>();
</pre>
<p>
In this example, <code>p1</code> and <code>p2</code> share data until QPainter::begin() is
called for <code>p2,</code> because painting a pixmap will modify it.  The same
happens also if anything is <a href="qpaintdevice.html#b2">bitBlt()</a>'ed into <code>p2.</code>

<p><address><hr><div align="center">
<table width="100%" cellspacing="0" border="0"><tr>
<td>Copyright  1999 Troll Tech<td><a href="trademarks.html">Trademarks</a>
<td align="right"><div align="right">Qt version 1.45</div>
</table></div></address></body></html>