1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 2<html> 3<head> 4<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 5<title>Pitfalls</title> 6<link rel="stylesheet" href="../../../doc/src/boostbook.css" type="text/css"> 7<meta name="generator" content="DocBook XSL Stylesheets V1.79.1"> 8<link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset"> 9<link rel="up" href="../foreach.html" title="Chapter 15. Boost.Foreach"> 10<link rel="prev" href="portability.html" title="Portability"> 11<link rel="next" href="history_and_acknowledgements.html" title="History and Acknowledgements"> 12</head> 13<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> 14<table cellpadding="2" width="100%"><tr> 15<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../boost.png"></td> 16<td align="center"><a href="../../../index.html">Home</a></td> 17<td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td> 18<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> 19<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> 20<td align="center"><a href="../../../more/index.htm">More</a></td> 21</tr></table> 22<hr> 23<div class="spirit-nav"> 24<a accesskey="p" href="portability.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../foreach.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="history_and_acknowledgements.html"><img src="../../../doc/src/images/next.png" alt="Next"></a> 25</div> 26<div class="section"> 27<div class="titlepage"><div><div><h2 class="title" style="clear: both"> 28<a name="foreach.pitfalls"></a><a class="link" href="pitfalls.html" title="Pitfalls">Pitfalls</a> 29</h2></div></div></div> 30<p> 31 This section describes some common pitfalls with <code class="literal">BOOST_FOREACH</code>. 32 </p> 33<h3> 34<a name="foreach.pitfalls.h0"></a> 35 <span class="phrase"><a name="foreach.pitfalls.types_with_commas"></a></span><a class="link" href="pitfalls.html#foreach.pitfalls.types_with_commas">Types 36 With Commas</a> 37 </h3> 38<p> 39 Since <code class="literal">BOOST_FOREACH</code> is a macro, it must have exactly two 40 arguments, with exactly one comma separating them. That's not always convenient, 41 especially when the type of the loop variable is a template. Consider trying 42 to iterate over a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span></code>: 43 </p> 44<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">m</span><span class="special">;</span> 45 46<span class="comment">// ERROR! Too many arguments to BOOST_FOREACH macro.</span> 47<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"><</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">int</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">// ...</span> 48</pre> 49<p> 50 One way to fix this is with a typedef. 51 </p> 52<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">m</span><span class="special">;</span> 53<span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">pair_t</span><span class="special">;</span> 54 55<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">// ...</span> 56</pre> 57<p> 58 Another way to fix it is to predeclare the loop variable: 59 </p> 60<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">map</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">int</span><span class="special">></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"><</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">int</span><span class="special">></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">// ...</span> 64</pre> 65<h3> 66<a name="foreach.pitfalls.h1"></a> 67 <span class="phrase"><a name="foreach.pitfalls.hoisting_and_iterator_invalidation"></a></span><a class="link" href="pitfalls.html#foreach.pitfalls.hoisting_and_iterator_invalidation">Hoisting 68 and Iterator Invalidation</a> 69 </h3> 70<p> 71 Under the covers, <code class="literal">BOOST_FOREACH</code> uses iterators to traverse 72 the element sequence. Before the loop is executed, the end iterator is cached 73 in a local variable. This is called <span class="emphasis"><em>hoisting</em></span>, and it is 74 an important optimization. It assumes, however, that the end iterator of the 75 sequence is stable. It usually is, but if we modify the sequence by adding 76 or removing elements while we are iterating over it, we may end up hoisting 77 ourselves on our own petard. 78 </p> 79<p> 80 Consider the following code: 81 </p> 82<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></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"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></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> 93<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"><</span><span class="keyword">int</span><span class="special">>::</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> 94 <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> 95<span class="special">{</span> 96 <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> 97 <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!</span> 98<span class="special">}</span> 99</pre> 100<p> 101 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> 102 will cause all iterators into <code class="computeroutput"><span class="identifier">vect</span></code> 103 to become invalid, including <code class="computeroutput"><span class="identifier">it1</span></code> 104 and <code class="computeroutput"><span class="identifier">it2</span></code>. The next iteration 105 through the loop will cause the invalid iterators to be used. That's bad news. 106 </p> 107<p> 108 The moral of the story is to think twice before adding and removing elements 109 from the sequence over which you are iterating. If doing so could cause iterators 110 to become invalid, don't do it. Use a regular <code class="computeroutput"><span class="keyword">for</span></code> 111 loop instead. 112 </p> 113</div> 114<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> 115<td align="left"></td> 116<td align="right"><div class="copyright-footer">Copyright © 2004 Eric Niebler<p> 117 Distributed under the Boost Software License, Version 1.0. (See accompanying 118 file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) 119 </p> 120</div></td> 121</tr></table> 122<hr> 123<div class="spirit-nav"> 124<a accesskey="p" href="portability.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../foreach.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="history_and_acknowledgements.html"><img src="../../../doc/src/images/next.png" alt="Next"></a> 125</div> 126</body> 127</html> 128