Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/doc/html/foreach/pitfalls.html @ 46

Last change on this file since 46 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 10.5 KB
Line 
1<html>
2<head>
3<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
4<title>Pitfalls</title>
5<link rel="stylesheet" href="../boostbook.css" type="text/css">
6<meta name="generator" content="DocBook XSL Stylesheets V1.68.1">
7<link rel="start" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset">
8<link rel="up" href="../foreach.html" title="Chapter 5. Boost.Foreach">
9<link rel="prev" href="portability.html" title="Portability">
10<link rel="next" href="history_and_acknowledgements.html" title="History and Acknowledgements">
11</head>
12<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
13<table cellpadding="2" width="100%">
14<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../boost.png"></td>
15<td align="center"><a href="../../../index.htm">Home</a></td>
16<td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td>
17<td align="center"><a href="../../../people/people.htm">People</a></td>
18<td align="center"><a href="../../../more/faq.htm">FAQ</a></td>
19<td align="center"><a href="../../../more/index.htm">More</a></td>
20</table>
21<hr>
22<div class="spirit-nav">
23<a accesskey="p" href="portability.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../foreach.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="history_and_acknowledgements.html"><img src="../images/next.png" alt="Next"></a>
24</div>
25<div class="section" lang="en">
26<div class="titlepage"><div><div><h2 class="title" style="clear: both">
27<a name="foreach.pitfalls"></a>Pitfalls</h2></div></div></div>
28<p>
29      This section describes some common pitfalls with <code class="literal">BOOST_FOREACH</code>.
30    </p>
31<a name="foreach.pitfalls.types_with_commas"></a><h2>
32<a name="id1184829"></a>
33      Types With Commas
34    </h2>
35<p>
36      Since <code class="literal">BOOST_FOREACH</code> is a macro, it must have exactly two
37      arguments, with exactly one comma separating them. That's not always convenient,
38      especially when the type of the loop variable is a template. Consider trying
39      to iterate over a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span></code>:
40    </p>
41<pre class="programlisting">
42<span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">m</span><span class="special">;</span>
43
44<span class="comment">// ERROR! Too many arguments to BOOST_FOREACH macro.
45</span><span class="identifier">BOOST_FOREACH</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">p</span><span class="special">,</span> <span class="identifier">m</span><span class="special">)</span> <span class="comment">// ...
46</span></pre>
47<p>
48      One way to fix this is with a typedef.
49    </p>
50<pre class="programlisting">
51<span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">m</span><span class="special">;</span>
52<span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">pair_t</span><span class="special">;</span>
53
54<span class="identifier">BOOST_FOREACH</span><span class="special">(</span><span class="identifier">pair_t</span> <span class="identifier">p</span><span class="special">,</span> <span class="identifier">m</span><span class="special">)</span> <span class="comment">// ...
55</span></pre>
56<p>
57      Another way to fix it is to predeclare the loop variable:
58    </p>
59<pre class="programlisting">
60<span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">m</span><span class="special">;</span>
61<span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">p</span><span class="special">;</span>
62
63<span class="identifier">BOOST_FOREACH</span><span class="special">(</span><span class="identifier">p</span><span class="special">,</span> <span class="identifier">m</span><span class="special">)</span> <span class="comment">// ...
64</span></pre>
65<a name="foreach.pitfalls.hoisting_and_iterator_invalidation"></a><h2>
66<a name="id1185275"></a>
67      Hoisting and Iterator Invalidation
68    </h2>
69<p>
70      Under the covers, <code class="literal">BOOST_FOREACH</code> uses iterators to traverse
71      the element sequence. Before the loop is executed, the end iterator is cached
72      in a local variable. This is called <span class="emphasis"><em>hoisting</em></span>, and it is
73      an important optimization. It assumes, however, that the end iterator of the
74      sequence is stable. It usually is, but if we modify the sequence by adding
75      or removing elements while we are iterating over it, we may end up hoisting
76      ourselves on our own petard.
77    </p>
78<p>
79      Consider the following code:
80    </p>
81<pre class="programlisting">
82<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">vect</span><span class="special">(</span><span class="number">4</span><span class="special">,</span> <span class="number">4</span><span class="special">);</span>
83<span class="identifier">BOOST_FOREACH</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span><span class="special">,</span> <span class="identifier">vect</span><span class="special">)</span>
84<span class="special">{</span>
85    <span class="identifier">vect</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">i</span> <span class="special">+</span> <span class="number">1</span><span class="special">);</span>
86<span class="special">}</span>
87</pre>
88<p>
89      This code will compile, but it has undefined behavior. That is because it is
90      logically equivalent to the following:
91    </p>
92<pre class="programlisting">
93<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">vect</span><span class="special">(</span><span class="number">4</span><span class="special">,</span> <span class="number">4</span><span class="special">);</span>
94<span class="keyword">for</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;::</span><span class="identifier">iterator</span> <span class="identifier">it1</span> <span class="special">=</span> <span class="identifier">vect</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">it2</span> <span class="special">=</span> <span class="identifier">vect</span><span class="special">.</span><span class="identifier">end</span><span class="special">();</span>
95    <span class="identifier">it1</span> <span class="special">!=</span> <span class="identifier">it2</span><span class="special">;</span> <span class="special">++</span><span class="identifier">it1</span><span class="special">)</span>
96<span class="special">{</span>
97    <span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="special">*</span><span class="identifier">it1</span><span class="special">;</span>
98    <span class="identifier">vect</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">i</span> <span class="special">+</span> <span class="number">1</span><span class="special">);</span> <span class="comment">// Oops! This invalidates it1 and it2!
99</span><span class="special">}</span>
100</pre>
101<p>
102      The call to <code class="computeroutput"><span class="identifier">vect</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">()</span></code>
103      will cause all iterators into <code class="computeroutput"><span class="identifier">vect</span></code>
104      to become invalid, including <code class="computeroutput"><span class="identifier">it1</span></code>
105      and <code class="computeroutput"><span class="identifier">it2</span></code>. The next iteration
106      through the loop will cause the invalid iterators to be used. That's bad news.
107    </p>
108<p>
109      The moral of the story is to think twice before adding and removing elements
110      from the sequence over which you are iterating. If doing so could cause iterators
111      to become invalid, don't do it. Use a regular <code class="computeroutput"><span class="keyword">for</span></code>
112      loop instead.
113    </p>
114</div>
115<table width="100%"><tr>
116<td align="left"></td>
117<td align="right"><small>Copyright © 2004 Eric Niebler</small></td>
118</tr></table>
119<hr>
120<div class="spirit-nav">
121<a accesskey="p" href="portability.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../foreach.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="history_and_acknowledgements.html"><img src="../images/next.png" alt="Next"></a>
122</div>
123</body>
124</html>
Note: See TracBrowser for help on using the repository browser.