<!--
    Licensed to the Apache Software  Foundation (ASF) under one or more
    contributor  license agreements.  See  the NOTICE  file distributed
    with  this  work  for  additional information  regarding  copyright
    ownership.   The ASF  licenses this  file to  you under  the Apache
    License, Version  2.0 (the  License); you may  not use  this file
    except in  compliance with the License.   You may obtain  a copy of
    the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the  License is distributed on an  "AS IS" BASIS,
    WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
    implied.   See  the License  for  the  specific language  governing
    permissions and limitations under the License.

    Copyright 1999-2007 Rogue Wave Software, Inc.
-->

<HTML>
<HEAD>
<TITLE>Insert Iterators</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Apache stdcxx Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="2-3.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="2-5.html"><IMG SRC="images/bnext.gif" WIDTH=25 HEIGHT=21 ALT="Next file" BORDER=O></A><DIV CLASS="DOCUMENTNAME"><B>Apache C++ Standard Library User's Guide</B></DIV>
<H2>2.4 Insert Iterators</H2>
<A NAME="idx38"><!></A>
<P>Assignment to the dereferenced value of an output iterator is normally used to <I>overwrite </I>the contents of an existing location. For example, the following invocation of the function <SAMP>std::copy()</SAMP> transfers values from one vector to another, although the space for the second vector was already set aside and even initialized by the declaration statement:</P>

<UL><PRE>
std::vector&lt;int&gt; a(10);
std::vector&lt;int&gt; b(10);
   // ...
std::copy(a.begin(), a.end(), b.begin());
</PRE></UL>
<P>Even structures such as lists can be overwritten in this fashion. In the following code, the list named <SAMP>c</SAMP> is assumed to have at least ten elements. The initial ten locations in the list will be replaced by the contents of the vector <SAMP>a</SAMP>.</P>

<UL><PRE>
std::list&lt;int&gt; c;
   // ...
std::copy(a.begin(), a.end(), c.begin());
</PRE></UL>
<P>With structures such as lists and sets, which are dynamically enlarged as new elements are added, it is frequently more appropriate to<I> insert</I> new values into the structure, rather than to <I>overwrite</I> existing locations. A type of adaptor called an <I>insert iterator</I> allows us to use algorithms such as <SAMP>std::copy()</SAMP> to insert into the associated container, rather than overwrite elements in the container. The output operations of the iterator are changed into insertions into the associated container. For example, the following code inserts the values of the vector <SAMP>a</SAMP> into an initially empty list:</P>

<UL><PRE>
std::list&lt;int&gt; d;

std::copy(a.begin(), a.end(), std::front_inserter(d));
</PRE></UL>
<A NAME="idx39"><!></A>
<P>There are three forms of insert iterators, all of which can be used to change a <I>copy</I> operation into an <I>insert</I> operation. The iterator generated using <SAMP>std::front_inserter()</SAMP>, shown above, inserts values into the front of the container. The iterator generated by <SAMP>std::back_inserter()</SAMP> places elements into the back of the container. Both forms can be used with <B><I><A HREF="../stdlibref/list.html">list</A></I></B>s and <B><I><A HREF="../stdlibref/deque.html">deque</A></I></B>s, but not with <B><I><A HREF="../stdlibref/set.html">set</A></I></B>s or <B><I><A HREF="../stdlibref/map.html">map</A></I></B>s. The iterator generated by <SAMP>std::back_inserter()</SAMP>, but not by <SAMP>std::front_inserter()</SAMP>, can be used with <B><I><A HREF="../stdlibref/vector.html">vector</A></I></B>.</P>
<A NAME="idx40"><!></A>
<P>The third and most general form of insert iterator is that generated by <SAMP>std::inserter()</SAMP>, which takes two arguments: a container and an iterator within the container. This form copies elements into the specified location in the container. (For a <B><I><A HREF="../stdlibref/list.html">list</A></I></B>, this means elements are copied immediately before the specified location). This form can be used with all the structures for which the previous two forms work, as well as with sets and maps.</P>
<P>The following simple program illustrates the use of all three forms of insert iterators. First, the values 3, 2, and 1 are inserted into the front of an initially empty list. Note that as each value is inserted, it becomes the new front, so that the resultant list is ordered 1, 2, 3. Next, the values 7, 8, and 9 are inserted into the end of the list. Finally, the <SAMP>find()</SAMP> operation is used to locate an iterator that denotes the 7 value, and the numbers 4, 5, and 6 are inserted immediately prior. The result is the list of numbers from 1 to 9 in order.</P>

<UL><PRE>
int main() {
   int threeToOne[]  = {3, 2, 1};
   int fourToSix[]   = {4, 5, 6};
   int sevenToNine[] = {7, 8, 9};

   std::list&lt;int&gt; aList;

   // first insert into the front
   // note that each value becomes new front
   std::copy(threeToOne, threeToOne+3, std::front_inserter(aList));

   // then insert into the back
   std::copy(sevenToNine, sevenToNine+3,
             std::back_inserter(aList));

   // find the seven, and insert into middle
   std::list&lt;int&gt;::iterator seven =
           std::find(aList.begin(), aList.end(), 7);
   std::copy(fourToSix, fourToSix+3, std::inserter(aList, seven));

   // copy result to output
   std::copy (aList.begin(), aList.end(), 
              std::ostream_iterator&lt;int,char&gt;(std::cout, " "));
   std::cout &lt;&lt; std::endl;
}
</PRE></UL>
<P>Note that there is an important and subtle difference between the iterator created by <SAMP>std::inserter()</SAMP> and the iterator created by <SAMP>std::front_inserter().</SAMP> The call on <SAMP>std::inserter()</SAMP> copies values in sequence, adding each one to the front of a list, whereas <SAMP>std::front_inserter()</SAMP> copies values making each value the new front. The result is that <SAMP>std::front_inserter()</SAMP> reverses the order of the original sequence, while <SAMP>std::inserter()</SAMP> retains the original order.</P>

<BR>
<HR>
<A HREF="2-3.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="2-5.html"><IMG SRC="images/bnext.gif" WIDTH=20 HEIGHT=21 ALT="Next file" BORDER=O></A>

<!-- Google Analytics tracking code -->
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
    _uacct = "UA-1775151-1";
    urchinTracker();
</script>
<!-- end of Google Analytics tracking code -->

</BODY>
</HTML>
