]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/libstdc++-v3/contrib/libstdc++-v3-4.4/doc/xml/manual/iterators.xml
update
[l4.git] / l4 / pkg / libstdc++-v3 / contrib / libstdc++-v3-4.4 / doc / xml / manual / iterators.xml
1 <?xml version='1.0'?>
2 <!DOCTYPE part PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" 
3  "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" 
4 [ ]>
5
6 <part id="manual.iterators" xreflabel="Iterators">
7 <?dbhtml filename="iterators.html"?>
8  
9 <partinfo>
10   <keywordset>
11     <keyword>
12       ISO C++
13     </keyword>
14     <keyword>
15       library
16     </keyword>
17   </keywordset>
18 </partinfo>
19
20 <title>
21   Iterators
22   <indexterm><primary>Iterators</primary></indexterm>
23 </title>
24
25 <!-- Chapter 01 : Predefined -->
26 <chapter id="manual.iterators.predefined" xreflabel="Predefined">
27   <title>Predefined</title>
28
29   <sect1 id="iterators.predefined.vs_pointers" xreflabel="Versus Pointers">
30     <title>Iterators vs. Pointers</title>
31    <para><ulink url="../faq/index.html#5_1">FAQ 5.1</ulink> points out that iterators
32       are not implemented as pointers.  They are a generalization of
33       pointers, but they are implemented in libstdc++ as separate classes.
34    </para>
35    <para>Keeping that simple fact in mind as you design your code will
36       prevent a whole lot of difficult-to-understand bugs.
37    </para>
38    <para>You can think of it the other way 'round, even.  Since iterators
39       are a generalization, that means that <emphasis>pointers</emphasis> are
40       <emphasis>iterators</emphasis>, and that pointers can be used whenever an
41       iterator would be.  All those functions in the Algorithms chapter
42       of the Standard will work just as well on plain arrays and their
43       pointers.
44    </para>
45    <para>That doesn't mean that when you pass in a pointer, it gets wrapped
46       into some special delegating iterator-to-pointer class with a layer
47       of overhead.  (If you think that's the case anywhere, you don't
48       understand templates to begin with...)  Oh, no; if you pass
49       in a pointer, then the compiler will instantiate that template
50       using T* as a type, and good old high-speed pointer arithmetic as
51       its operations, so the resulting code will be doing exactly the same
52       things as it would be doing if you had hand-coded it yourself (for
53       the 273rd time).
54    </para>
55    <para>How much overhead <emphasis>is</emphasis> there when using an iterator class?
56       Very little.  Most of the layering classes contain nothing but
57       typedefs, and typedefs are &quot;meta-information&quot; that simply
58       tell the compiler some nicknames; they don't create code.  That
59       information gets passed down through inheritance, so while the
60       compiler has to do work looking up all the names, your runtime code
61       does not.  (This has been a prime concern from the beginning.)
62    </para>
63  
64
65   </sect1>
66
67   <sect1 id="iterators.predefined.end" xreflabel="end() Is One Past the End">
68     <title>One Past the End</title>
69
70    <para>This starts off sounding complicated, but is actually very easy,
71       especially towards the end.  Trust me.
72    </para>
73    <para>Beginners usually have a little trouble understand the whole
74       'past-the-end' thing, until they remember their early algebra classes
75       (see, they <emphasis>told</emphasis> you that stuff would come in handy!) and
76       the concept of half-open ranges.
77    </para>
78    <para>First, some history, and a reminder of some of the funkier rules in
79       C and C++ for builtin arrays.  The following rules have always been
80       true for both languages:
81    </para>
82    <orderedlist>
83       <listitem>
84         <para>You can point anywhere in the array, <emphasis>or to the first element
85           past the end of the array</emphasis>.  A pointer that points to one
86           past the end of the array is guaranteed to be as unique as a
87           pointer to somewhere inside the array, so that you can compare
88           such pointers safely.
89         </para>
90       </listitem>
91       <listitem>
92         <para>You can only dereference a pointer that points into an array.
93           If your array pointer points outside the array -- even to just
94           one past the end -- and you dereference it, Bad Things happen.
95         </para>
96       </listitem>
97       <listitem>
98         <para>Strictly speaking, simply pointing anywhere else invokes
99           undefined behavior.  Most programs won't puke until such a
100           pointer is actually dereferenced, but the standards leave that
101           up to the platform.
102         </para>
103       </listitem>
104    </orderedlist>
105    <para>The reason this past-the-end addressing was allowed is to make it
106       easy to write a loop to go over an entire array, e.g.,
107       while (*d++ = *s++);.
108    </para>
109    <para>So, when you think of two pointers delimiting an array, don't think
110       of them as indexing 0 through n-1.  Think of them as <emphasis>boundary
111       markers</emphasis>:
112    </para>
113    <programlisting>
114
115    beginning            end
116      |                   |
117      |                   |               This is bad.  Always having to
118      |                   |               remember to add or subtract one.
119      |                   |               Off-by-one bugs very common here.
120      V                   V
121         array of N elements
122      |---|---|--...--|---|---|
123      | 0 | 1 |  ...  |N-2|N-1|
124      |---|---|--...--|---|---|
125
126      ^                       ^
127      |                       |
128      |                       |           This is good.  This is safe.  This
129      |                       |           is guaranteed to work.  Just don't
130      |                       |           dereference 'end'.
131    beginning                end
132
133    </programlisting>
134    <para>See?  Everything between the boundary markers is part of the array.
135       Simple.
136    </para>
137    <para>Now think back to your junior-high school algebra course, when you
138       were learning how to draw graphs.  Remember that a graph terminating
139       with a solid dot meant, &quot;Everything up through this point,&quot;
140       and a graph terminating with an open dot meant, &quot;Everything up
141       to, but not including, this point,&quot; respectively called closed
142       and open ranges?  Remember how closed ranges were written with
143       brackets, <emphasis>[a,b]</emphasis>, and open ranges were written with parentheses,
144       <emphasis>(a,b)</emphasis>?
145    </para>
146    <para>The boundary markers for arrays describe a <emphasis>half-open range</emphasis>,
147       starting with (and including) the first element, and ending with (but
148       not including) the last element:  <emphasis>[beginning,end)</emphasis>.  See, I
149       told you it would be simple in the end.
150    </para>
151    <para>Iterators, and everything working with iterators, follows this same
152       time-honored tradition.  A container's <code>begin()</code> method returns
153       an iterator referring to the first element, and its <code>end()</code>
154       method returns a past-the-end iterator, which is guaranteed to be
155       unique and comparable against any other iterator pointing into the
156       middle of the container.
157    </para>
158    <para>Container constructors, container methods, and algorithms, all take
159       pairs of iterators describing a range of values on which to operate.
160       All of these ranges are half-open ranges, so you pass the beginning
161       iterator as the starting parameter, and the one-past-the-end iterator
162       as the finishing parameter.
163    </para>
164    <para>This generalizes very well.  You can operate on sub-ranges quite
165       easily this way; functions accepting a <emphasis>[first,last)</emphasis> range
166       don't know or care whether they are the boundaries of an entire {array,
167       sequence, container, whatever}, or whether they only enclose a few
168       elements from the center.  This approach also makes zero-length
169       sequences very simple to recognize:  if the two endpoints compare
170       equal, then the {array, sequence, container, whatever} is empty.
171    </para>
172    <para>Just don't dereference <code>end()</code>.
173    </para>
174
175   </sect1>
176 </chapter>
177
178 <!-- Chapter 02 : Stream -->
179
180 </part>