﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-舞影凌乱-随笔分类-STL</title><link>http://www.cppblog.com/lovefeel2004/category/11594.html</link><description>专注C/C++，Linux</description><language>zh-cn</language><lastBuildDate>Wed, 23 Jun 2010 06:58:17 GMT</lastBuildDate><pubDate>Wed, 23 Jun 2010 06:58:17 GMT</pubDate><ttl>60</ttl><item><title>STL vector 容器介绍</title><link>http://www.cppblog.com/lovefeel2004/archive/2010/06/23/118556.html</link><dc:creator>幽梦新影</dc:creator><author>幽梦新影</author><pubDate>Wed, 23 Jun 2010 05:56:00 GMT</pubDate><guid>http://www.cppblog.com/lovefeel2004/archive/2010/06/23/118556.html</guid><wfw:comment>http://www.cppblog.com/lovefeel2004/comments/118556.html</wfw:comment><comments>http://www.cppblog.com/lovefeel2004/archive/2010/06/23/118556.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lovefeel2004/comments/commentRss/118556.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lovefeel2004/services/trackbacks/118556.html</trackback:ping><description><![CDATA[<p><strong><span>介绍</span></strong><strong></strong></p>
<p><span>这篇文章的目的是为了介绍</span><span>std::vector</span><span>，如何恰当地使用它们的成员函数等操作。本文中还讨论了条件函数和函数指针在迭代算法中使用，如在</span><span>remove_if()</span><span>和</span><span>for_each()</span><span>中的使用。通过阅读这篇文章读者应该能够有效地使用</span><span>vector</span><span>容器，而且应该不会再去使用</span><span>C</span><span>类型的动态数组了。</span></p>
<p><strong>&nbsp;</strong></p>
<p><strong><span>Vector</span></strong><strong><span>总览</span></strong><strong></strong></p>
<p><span>vector</span><span>是</span><span>C++</span><span>标准模板库中的部分内容，它是一个多功能的，能够操作多种数据结构和算法的模板类和函数库。</span><span>vector</span><span>之所以被认为是一个容器，是因为它能够像容器一样存放各种类型的对象，简单地说，</span><span>vector</span><span>是一个能够存放任意类型的动态数组，能够增加和压缩数据。</span></p>
<p><span>为了可以使用</span><span>vector</span><span>，必须在你的头文件中包含下面的代码：</span><strong></strong></p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td vAlign=top width=528>
            <p><span>#</span><span>include</span><span> &lt;vector&gt;</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>
<p><span>vector</span><span>属于</span><span>std</span><span>命名域的，因此需要通过命名限定，如下完成你的代码：</span><strong></strong></p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td vAlign=top width=528>
            <p><span>using</span><span> std::vector;</span></p>
            <p><span>vector&lt;</span><span>int</span><span>&gt; vInts;</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>
<p><span>或者连在一起，使用全名：</span><strong></strong></p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td vAlign=top width=528>
            <p><span>std::vector&lt;</span><span>int</span><span>&gt; vInts;</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>
<p><span>建议使用全局的命名域方式：</span><strong></strong></p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td vAlign=top width=528>
            <p><span>using</span><span> </span><span>namespace</span><span> std;</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>
<p><span>在后面的操作中全局的命名域方式会造成一些问题。</span><span>vector</span><span>容器提供了很多接口，在下面的表中列出</span><span>vector</span><span>的成员函数和操作。</span></p>
<p><strong>&nbsp;</strong></p>
<p><strong><span>Vector</span></strong><strong><span>成员函数</span></strong><strong></strong></p>
<div align=center>
<table cellSpacing=1 cellPadding=0 width="90%" border=1>
    <tbody>
        <tr>
            <td width="33%">
            <p><span>函数</span></p>
            </td>
            <td width="66%">
            <p><span>表述</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>c.assign(beg,end)</span></p>
            <p><span>c.assign(n,elem)</span></p>
            </td>
            <td width="66%">
            <p><span>将</span><span>[beg; end)</span><span>区间中的数据赋值给</span><span>c</span><span>。</span></p>
            <p><span>将</span><span>n</span><span>个</span><span>elem</span><span>的拷贝赋值给</span><span>c</span><span>。</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>c.at(idx)</span></p>
            </td>
            <td width="66%">
            <p><span>传回索引</span><span>idx</span><span>所指的数据，如果</span><span>idx</span><span>越界，抛出</span><span>out_of_range</span><span>。</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>c.back()</span></p>
            </td>
            <td width="66%">
            <p><span>传回最后一个数据，不检查这个数据是否存在。</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>c.begin()</span></p>
            </td>
            <td width="66%">
            <p><span>传回迭代器重的可一个数据。</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>c.capacity()</span></p>
            </td>
            <td width="66%">
            <p><span>返回容器中数据个数。</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>c.clear()</span></p>
            </td>
            <td width="66%">
            <p><span>移除容器中所有数据。</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>c.empty()</span></p>
            </td>
            <td width="66%">
            <p><span>判断容器是否为空。</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>c.end()</span></p>
            </td>
            <td width="66%">
            <p><span>指向迭代器中的最后一个数据地址。</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>c.erase(pos)</span></p>
            <p><span>c.erase(beg,end)</span></p>
            </td>
            <td width="66%">
            <p><span>删除</span><span>pos</span><span>位置的数据，传回下一个数据的位置。</span></p>
            <p><span>删除</span><span>[beg,end)</span><span>区间的数据，传回下一个数据的位置</span><span>。</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>c.front()</span></p>
            </td>
            <td width="66%">
            <p><span>传回地一个数据。</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>get_allocator</span></p>
            </td>
            <td width="66%">
            <p><span>使用构造函数返回一个拷贝。</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>c.insert(pos,elem) </span></p>
            <p><span>c.insert(pos,n,elem)</span></p>
            <p><span>c.insert(pos,beg,end)</span></p>
            </td>
            <td width="66%">
            <p><span>在</span><span>pos</span><span>位置插入一个</span><span>elem</span><span>拷贝，传回新数据位置。</span></p>
            <p><span>在</span><span>pos</span><span>位置插入</span><span>n</span><span>个</span><span>elem</span><span>数据。无返回值。</span></p>
            <p><span>在</span><span>pos</span><span>位置插入在</span><span>[beg,end)</span><span>区间的数据。无返回值。</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>c.max_size()</span></p>
            </td>
            <td width="66%">
            <p><span>返回容器中最大数据的数量。</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>c.pop_back()</span></p>
            </td>
            <td width="66%">
            <p><span>删除最后一个数据。</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>c.push_back(elem)</span></p>
            </td>
            <td width="66%">
            <p><span>在尾部加入一个数据。</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>c.rbegin()</span></p>
            </td>
            <td width="66%">
            <p><span>传回一个逆向队列的第一个数据。</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>c.rend()</span></p>
            </td>
            <td width="66%">
            <p><span>传回一个逆向队列的最后一个数据的下一个位置。</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>c.resize(num)</span></p>
            </td>
            <td width="66%">
            <p><span>重新指定队列的长度。</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>c.reserve()</span></p>
            </td>
            <td width="66%">
            <p><span>保留适当的容量。</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>c.size()</span></p>
            </td>
            <td width="66%">
            <p><span>返回容器中实际数据的个数。</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>c1.swap(c2) </span></p>
            <p><span>swap(c1,c2)</span></p>
            </td>
            <td width="66%">
            <p><span>将</span><span>c1</span><span>和</span><span>c2</span><span>元素互换。</span></p>
            <p><span>同上操作。</span></p>
            </td>
        </tr>
        <tr>
            <td width="33%">
            <p><span>vector&lt;Elem&gt; c</span></p>
            <p><span>vector &lt;Elem&gt; c1(c2)</span></p>
            <p><span>vector &lt;Elem&gt; c(n)</span></p>
            <p><span>vector &lt;Elem&gt; c(n, elem)</span></p>
            <p><span>vector &lt;Elem&gt; c(beg,end)</span></p>
            <p><span>c.~ vector &lt;Elem&gt;()</span></p>
            </td>
            <td width="66%">
            <p><span>创建一个空的</span><span>vector</span><span>。</span></p>
            <p><span>复制一个</span><span>vector</span><span>。</span></p>
            <p><span>创建一个</span><span>vector</span><span>，含有</span><span>n</span><span>个数据，数据均已缺省构造产生</span><span>。</span></p>
            <p><span>创建一个含有</span><span>n</span><span>个</span><span>elem</span><span>拷贝的</span><span>vector</span><span>。</span></p>
            <p><span>创建一个以</span><span>[beg;end)</span><span>区间的</span><span>vector</span><span>。</span></p>
            <p><span>销毁所有数据，释放内存。</span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p>&nbsp;</p>
<p><strong><span>Vector</span></strong><strong><span>操作</span></strong><strong></strong></p>
<div align=center>
<table cellSpacing=1 cellPadding=0 width="90%" border=1>
    <tbody>
        <tr>
            <td width="32%">
            <p align=left><span>函数</span></p>
            </td>
            <td width="66%">
            <p align=left><span>描述</span></p>
            </td>
        </tr>
        <tr>
            <td width="32%">
            <p><span>operator</span><span>[]</span><span> </span></p>
            </td>
            <td width="66%">
            <p><span>返回容器中指定位置的一个引用。</span></p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p><strong>&nbsp;</strong></p>
<p><strong><span>创建一个</span></strong><strong><span>vector</span></strong></p>
<p><span>vector</span><span>容器提供了多种创建方法，下面介绍几种常用的。</span></p>
<p><span>创建一个</span><span>Widget</span><span>类型的空的</span><span>vector</span><span>对象：</span><strong></strong></p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td vAlign=top width=528>
            <p><span>vector&lt;Widget&gt; vWidgets;</span></p>
            <p><span>//<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>------</span></p>
            <p><span>//<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>|</span></p>
            <p><span>//<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>|- Since vector is a container, its member functions</span></p>
            <p><span>//<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>operate on iterators and the container itself so </span></p>
            <p><span>//<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>it can hold objects of any type.</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>
<p><span>创建一个包含</span><span>500</span><span>个</span><span>Widget</span><span>类型数据的</span><span>vector</span><span>：</span><strong></strong></p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td vAlign=top width=528>
            <p><span>vector&lt;Widget&gt; vWidgets(500);</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>
<p><span>创建一个包含</span><span>500</span><span>个</span><span>Widget</span><span>类型数据的</span><span>vector</span><span>，并且都初始化为</span><span>0</span><span>：</span><strong></strong></p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td vAlign=top width=528>
            <p><span>vector&lt;Widget&gt; vWidgets(500, Widget(0));</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>
<p><span>创建一个</span><span>Widget</span><span>的拷贝：</span><strong></strong></p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td vAlign=top width=528>
            <p><span>vector&lt;Widget&gt; vWidgetsFromAnother(vWidgets);</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p><strong>&nbsp;</strong></p>
<p><strong><span>向</span></strong><strong><span>vector</span></strong><strong><span>添加一个数据</span></strong><strong></strong></p>
<p><span>vector</span><span>添加数据的缺省方法是</span><span>push_back()</span><span>。</span><span>push_back()</span><span>函数表示将数据添加到</span><span>vector</span><span>的尾部，并按需要来分配内存。例如：向</span><span>vector&lt;Widget&gt;</span><span>中添加</span><span>10</span><span>个数据，需要如下编写代码：</span><strong></strong></p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td vAlign=top width=528>
            <p><span>for</span><span>(int i= 0;i&lt;10; i++)</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp; </span>vWidgets.push_back(Widget(i));</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p><strong>&nbsp;</strong></p>
<p><strong><span>获取</span></strong><strong><span>vector</span></strong><strong><span>中制定位置的数据</span></strong><strong></strong></p>
<p><span>很多时候我们不必要知道</span><span>vector</span><span>里面有多少数据，</span><span>vector</span><span>里面的数据是动态分配的，使用</span><span>push_back()</span><span>的一系列分配空间常常决定于文件或一些数据源。如果你想知道</span><span>vector</span><span>存放了多少数据，你可以使用</span><span>empty()</span><span>。获取</span><span>vector</span><span>的大小，可以使用</span><span>size()</span><span>。例如，如果你想获取一个</span><span>vector v</span><span>的大小，但不知道它是否为空，或者已经包含了数据，如果为空想设置为</span><span>-1</span><span>，你可以使用下面的代码实现：</span><strong></strong></p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td vAlign=top width=528>
            <p><span>int</span><span> nSize = v.empty() ? -1 : </span><span>static_cast</span><span>&lt;</span><span>int</span><span>&gt;(v.size());</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>
<p><strong><span>访问</span></strong><strong><span>vector</span></strong><strong><span>中的数据</span></strong><strong></strong></p>
<p><span>使用两种方法来访问</span><span>vector</span><span>。</span></p>
<p><span><span>1、<span>&nbsp;&nbsp; </span></span></span><span>vector::at()</span></p>
<p><span><span>2、<span>&nbsp;&nbsp; </span></span></span><span>vector::operator[]</span></p>
<p><span>operator[]</span><span>主要是为了与</span><span>C</span><span>语言进行兼容。它可以像</span><span>C</span><span>语言数组一样操作。但</span><span>at()</span><span>是我们的首选，因为</span><span>at()</span><span>进行了边界检查，如果访问超过了</span><span>vector</span><span>的范围，将抛出一个例外。由于</span><span>operator[]</span><span>容易造成一些错误，所有我们很少用它，下面进行验证一下：</span></p>
<p><span>分析下面的代码：</span></p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td vAlign=top width=528>
            <p><span>vector&lt;</span><span>int</span><span>&gt; v;</span></p>
            <p><span>v.reserve(10);</span></p>
            <p>&nbsp;</p>
            <p><span>for</span><span>(</span><span>int</span><span> i=0; i&lt;7; i++)</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp; </span>v.push_back(i);</span></p>
            <p>&nbsp;</p>
            <p><span>try</span></p>
            <p><span>{</span></p>
            <p><span>&nbsp;</span><span>int</span><span> iVal1 = v[7];&nbsp;// not bounds checked - will not throw</span></p>
            <p><span>&nbsp;</span><span>int</span><span> iVal2 = v.at(7); // bounds checked - will throw if out of range</span></p>
            <p><span>}</span></p>
            <p><span>catch</span><span>(</span><span>const</span><span> exception&amp; e)</span></p>
            <p><span>{</span></p>
            <p><span>&nbsp;cout &lt;&lt; e.what();</span></p>
            <p><span>}</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>
<p><span>我们使用</span><span>reserve()</span><span>分配了</span><span>10</span><span>个</span><span>int</span><span>型的空间，但并不没有初始化。如下图所示：<br></span></p>
<p align=center><img alt="" hspace=0 src="http://www.codeproject.com/vcpp/stl/std_vector/vector_01.gif" align=baseline border=0></p>
<p align=right><br></p>
<span>
<p><span>你可以在这个代码中尝试不同条件，观察它的结果，但是无论何时使用</span><span>at()</span><span>，都是正确的。</span></p>
<p><strong><span><font size=3>&nbsp;</font></span></strong></p>
<p><font size=3><strong><span>删除</span></strong><strong><span>vector</span></strong><strong><span>中的数据</span></strong><strong></strong></font></p>
<p><span>vector</span><span>能够非常容易地添加数据，也能很方便地取出数据，同样</span><span>vector</span><span>提供了</span><span>erase()</span><span>，</span><span>pop_back()</span><span>，</span><span>clear()</span><span>来删除数据，当你删除数据的时候，你应该知道要删除尾部的数据，或者是删除所有数据，还是个别的数据。在考虑删除等操作之前让我们静下来考虑一下在</span><span>STL</span><span>中的一些应用。</span><span> </span></p>
<p><strong><span><font size=3>&nbsp;</font></span></strong></p>
<p><font size=3><strong><span>Remove_if()</span></strong><strong><span>算法</span></strong><strong></strong></font></p>
<p><span>现在我们考虑操作里面的数据。如果要使用</span><span>remove_if()</span><span>，我们需要在头文件中包含如下代码：：</span><strong></strong></p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td vAlign=top width=528>
            <p><span>#</span><span>include</span><span> &lt;algorithm&gt;</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Remove_if()</span><span>有三个参数：</span></p>
<p><span><span>1、<span>&nbsp;&nbsp; </span></span></span><span>iterator _First</span><span>：指向第一个数据的迭代指针。</span></p>
<p><span><span>2、<span>&nbsp;&nbsp; </span></span></span><span>iterator _Last</span><span>：指向最后一个数据的迭代指针。</span></p>
<p><span><span>3、<span>&nbsp;&nbsp; </span></span></span><span>predicate _Pred</span><span>：一个可以对迭代操作的条件函数。</span></p>
<p><strong><span><font size=3>&nbsp;</font></span></strong></p>
<p><font size=3><strong><span>条件函数</span></strong><strong></strong></font></p>
<p><span>条件函数是一个按照用户定义的条件返回是或否的结果，是最基本的函数指针，或者是一个函数对象。这个函数对象需要支持所有的函数调用操作，重载</span><span>operator()()</span><span>操作。</span><span>remove_if()</span><span>是通过</span><span>unary_function</span><span>继承下来的，允许传递数据作为条件。</span></p>
<p><span>例如，假如你想从一个</span><span>vector&lt;CString&gt;</span><span>中删除匹配的数据，如果字串中包含了一个值，从这个值开始，从这个值结束。首先你应该建立一个数据结构来包含这些数据，类似代码如下：</span><strong></strong></p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td vAlign=top width=528>
            <p><span>#</span><span>include</span><span> &lt;functional&gt;</span></p>
            <p><span>enum</span><span> findmodes </span></p>
            <p><span>{</span></p>
            <p><span>&nbsp;FM_INVALID = 0,</span></p>
            <p><span>&nbsp;FM_IS,</span></p>
            <p><span>&nbsp;FM_STARTSWITH,</span></p>
            <p><span>&nbsp;FM_ENDSWITH,</span></p>
            <p><span>&nbsp;FM_CONTAINS</span></p>
            <p><span>};</span></p>
            <p><span>typedef</span><span> </span><span>struct</span><span> tagFindStr</span></p>
            <p><span>{</span></p>
            <p><span>&nbsp;UINT iMode;</span></p>
            <p><span>&nbsp;CString szMatchStr;</span></p>
            <p><span>} FindStr;</span></p>
            <p><span>typedef</span><span> FindStr* LPFINDSTR;</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>
<p><span>然后处理条件判断：</span></p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td vAlign=top width=528>
            <p><span>class</span><span> FindMatchingString </span></p>
            <p><span><span>&nbsp;&nbsp; </span>&nbsp;: </span><span>public</span><span> std::unary_function&lt;CString, </span><span>bool</span><span>&gt; </span></p>
            <p><span>{</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp; </span></span></p>
            <p><span>public</span><span>: </span></p>
            <p><span>&nbsp;FindMatchingString(</span><span>const</span><span> LPFINDSTR lpFS) : m_lpFS(lpFS) {} </span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp; </span></span></p>
            <p><span>&nbsp;</span><span>bool</span><span> operator()(CString&amp; szStringToCompare) </span><span>const</span><span> </span></p>
            <p><span>&nbsp;{ </span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>bool</span><span> retVal = </span><span>false</span><span>;</span></p>
            <p>&nbsp;</p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>switch</span><span>(m_lpFS-&gt;iMode) </span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>case</span><span> FM_IS: </span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{ </span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>retVal = (szStringToCompare == m_lpFDD-&gt;szMatchStr); </span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>break</span><span>;</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>case</span><span> FM_STARTSWITH: </span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{ </span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>retVal = (szStringToCompare.Left(m_lpFDD-&gt;szMatchStr.GetLength())</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>&nbsp;&nbsp;</span>== m_lpFDD-&gt;szWindowTitle);</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;<span>&nbsp;&nbsp;&nbsp;</span></span><span>break</span><span>;</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>} </span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>case</span><span> FM_ENDSWITH: </span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>retVal = (szStringToCompare.Right(m_lpFDD-&gt;szMatchStr.GetLength()) </span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>== m_lpFDD-&gt;szMatchStr);</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>break</span><span>; </span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>} </span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp; </span>&nbsp;</span><span>case</span><span> FM_CONTAINS: </span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>retVal = (szStringToCompare.Find(m_lpFDD-&gt;szMatchStr) != -1);</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>break</span><span>; </span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>return</span><span> retVal;</span></p>
            <p><span>&nbsp;}</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
            <p><span>private</span><span>: </span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp; </span>LPFINDSTR m_lpFS;</span></p>
            <p><span>};</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>
<p><span>通过这个操作你可以从</span><span>vector</span><span>中有效地删除数据：</span></p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td vAlign=top width=528>
            <p><span>// remove all strings containing the value of </span></p>
            <p><span>// szRemove from vector&lt;CString&gt; vs.</span></p>
            <p>&nbsp;</p>
            <p><span>FindStr fs;</span></p>
            <p><span>fs.iMode = FM_CONTAINS;</span></p>
            <p><span>fs.szMatchStr = szRemove;</span></p>
            <p>&nbsp;</p>
            <p><span>vs.erase(std::remove_if(vs.begin(), vs.end(), FindMatchingString(&amp;fs)), vs.end());</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p><strong><span><font size=3>&nbsp;</font></span></strong></p>
<p><font size=3><strong><span>Remove_if()</span></strong><strong><span>能做什么？</span></strong><strong></strong></font></p>
<p><span>你可能会疑惑，对于上面那个例子在调用</span><span>remove_if()</span><span>的时候还要使用</span><span>erase()</span><span>呢？这是因为大家并不熟悉</span><span>STL</span><span>中的算法。</span><span>Remove(),remove_if(</span><span>)</span><span>等所有的移出操作都是建立在一个迭代范围上的，那么不能操作容器中的数据。所以在使用</span><span>remove_if()</span><span>，实际上操作的时容器里数据的上面的。思考上面的例子：</span></p>
<p><span><span>1、<span>&nbsp;&nbsp; </span></span></span><span>szRemove</span><span> = &#8220;o&#8221;.</span></p>
<p><span><span>2、<span>&nbsp;&nbsp; </span></span></span><span>vs</span><span>见下面图表中的显示。<br></span></p>
<p align=center><img alt="" hspace=0 src="http://www.codeproject.com/vcpp/stl/std_vector/vector_02.gif" align=baseline border=0></p>
<p><span>观察这个结果，我们可以看到</span><span>remove_if()</span><span>实际上是根据条件对迭代地址进行了修改，在数据的后面存在一些残余的数据，那些需要删除的数据。剩下的数据的位置可能不是原来的数据，但他们是不知道的。</span></p>
<p><span>调用</span><span>erase()</span><span>来删除那些残余的数据。注意上面例子中通过</span><span>erase()</span><span>删除</span><span>remove_if()</span><span>的结果和</span><span>vs.enc()</span><span>范围的数据。</span><strong></strong></p>
<p><strong><span><font face="Times New Roman" size=3>&nbsp;</font></span></strong></p>
<p><font size=3><strong><span>压缩一个臃肿的</span></strong><strong><span><font face="Times New Roman">vector</font></span></strong></font></p>
<p><span>很多时候大量的删除数据，或者通过使用</span><span>reserve()</span><span>，结果</span><span>vector</span><span>的空间远远大于实际需要的。所有需要压缩</span><span>vector</span><span>到它实际的大小。</span><span>resize()</span><span>能够增加</span><span>vector</span><span>的大小。</span><span>Clear()</span><span>仅仅能够改变缓存的大小，所有的这些对于</span><span>vector</span><span>释放内存等九非常重要了。如何来解决这些问题呢，让我们来操作一下。</span></p>
<p><span>我们可以通过一个</span><span>vector</span><span>创建另一个</span><span>vector</span><span>。让我们看看这将发生什么。假定我们已经有一个</span><span>vector v</span><span>，它的内存大小为</span><span><font face="Times New Roman">1000</font></span><span>，当我们调用</span><span>size()</span><span>的时候，它的大小仅为</span><span><font face="Times New Roman">7</font></span><span>。我们浪费了大量的内存。让我们在它的基础上创建一个</span><span>vector</span><span>。</span><strong></strong></p>
<p>&#160;</p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td vAlign=top width=528>
            <p><span>std::vector&lt;CString&gt; vNew(v);</span></p>
            <p><span>cout &lt;&lt; vNew.capacity();</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p><span><font face="Times New Roman">&nbsp;</font></span></p>
<p><span>vNew.capacity()</span><span>返回的是</span><span><font face="Times New Roman">7</font></span><span>。这说明新创建的只是根据实际大小来分配的空间。现在我们不想释放</span><span><font face="Times New Roman">v</font></span><span>，因为我们要在其它地方用到它，我们可以使用</span><span>swap()</span><span>将</span><span>v</span><span>和</span><span>vNew</span><span>互相交换一下？</span></p>
<p>&#160;</p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td vAlign=top width=528>
            <p><span><span>&nbsp;&nbsp;&nbsp; </span>vNew.swap(v);</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp; </span>cout &lt;&lt; vNew.capacity();</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp; </span>cout &lt;&lt; v.capacity();</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p><strong><span><font face="Times New Roman" size=3>&nbsp;</font></span></strong></p>
<p><span>有趣的是：</span><span>vNew.capacity()</span><span>是</span><span>1000</span><span>，</span><span>而</span><span>v.capacity()</span><span>是</span><span>7</span><span>。</span></p>
<p><span>现在是达到我的目的了，但是并不是很好的解决方法，我们可以像下面这么写：</span></p>
<p>&#160;</p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td vAlign=top width=528>
            <p><span><span>&nbsp;&nbsp;&nbsp; </span>std::vector&lt;CString&gt;(v).swap(v);</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p><strong><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></font></font></span></strong></p>
<p><span>你可以看到我们做了什么？我们创建了一个临时变量代替那个命名的，然后使用</span><span>swap()</span><span><font face="Times New Roman">,</font></span><span>这样我们就去掉了不必要的空间，得到实际大小的</span><span>v</span><span>。</span></p>
<p><strong><span><font face="Times New Roman" size=3>&nbsp;</font></span></strong></p>
<p><font size=3><strong><span>结论</span></strong><strong></strong></font></p>
<p><span>我希望这个文档可以给那些使用</span><span><font face="Times New Roman">STL </font></span><span>vector</span><span>容器的开发者很有价值的参考。我也希望通过阅读这篇文章你可以放心地使用</span><span>vector</span><span>来代替</span><span><font face="Times New Roman">C</font></span><span>语言中的数据了。</span><strong></strong></p>
<p><strong><span><font face="Times New Roman" size=3>&nbsp;</font></span></strong></p>
<p><font size=3><strong><span>参考</span></strong><strong></strong></font></p>
<p><span><font face="Times New Roman">Plauger, P.J. Standard C++ Library Reference. February, 2003. MSDN. </font></span></p>
<p><span><font face="Times New Roman">Schildt, Herbert. C++ from the Ground Up, Second Edition. <st1:city w:st="on"><st1:place w:st="on">Berkeley</st1:place></st1:city>: 1998. </font></span></p>
<p><span><font face="Times New Roman">Sutter, Herb. More Exceptional C++. <st1:city w:st="on"><st1:place w:st="on">Indianapolis</st1:place></st1:city>: 2002. </font></span></p>
</span>
<img src ="http://www.cppblog.com/lovefeel2004/aggbug/118556.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lovefeel2004/" target="_blank">幽梦新影</a> 2010-06-23 13:56 <a href="http://www.cppblog.com/lovefeel2004/archive/2010/06/23/118556.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>