﻿<?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++博客-微尘--KeepMoving-随笔分类-STL泛型编程</title><link>http://www.cppblog.com/tyt2008cn/category/6167.html</link><description>为了忘却的记忆</description><language>zh-cn</language><lastBuildDate>Thu, 22 May 2008 00:47:10 GMT</lastBuildDate><pubDate>Thu, 22 May 2008 00:47:10 GMT</pubDate><ttl>60</ttl><item><title>（转）深入研究 C++中的 STL Deque 容器</title><link>http://www.cppblog.com/tyt2008cn/archive/2008/02/29/43497.html</link><dc:creator>微尘</dc:creator><author>微尘</author><pubDate>Fri, 29 Feb 2008 14:04:00 GMT</pubDate><guid>http://www.cppblog.com/tyt2008cn/archive/2008/02/29/43497.html</guid><wfw:comment>http://www.cppblog.com/tyt2008cn/comments/43497.html</wfw:comment><comments>http://www.cppblog.com/tyt2008cn/archive/2008/02/29/43497.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tyt2008cn/comments/commentRss/43497.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tyt2008cn/services/trackbacks/43497.html</trackback:ping><description><![CDATA[<font id=font_word>&nbsp;
<p>&#160;</p>
本文档深入分析了std::deque，并提供了一个指导思想：当考虑到内存分配和执行性能的时候，使用std::deque要比std::vector好。<br><br>　　<strong>介绍<br></strong><br>　　本文深入地研究了std::deque 容器。本文将讨论在一些情况下使用deque&gt; 比vector更好。读完这篇文章后读者应该能够理解在容量增长的过程中deque 与vector在内存分配和性能的不同表现。由于deque&gt; 和vector的用法很相似，读者可以参考vector 文档中介绍如何使用STL容器。<br><br>　　<strong>Deque总览</strong><br><br>　　deque和vector一样都是标准模板库中的内容，deque是双端队列，在接口上和vector非常相似，在许多操作的地方可以直接替换。假如读者已经能够有效地使用vector容器，下面提供deque的成员函数和操作，进行对比参考。<br><br>　　<strong>Deque成员函数</strong><br><br>
<div align=center>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td width="33%">函数<br></td>
            <td width="66%">描述</td>
        </tr>
        <tr>
            <td>c.assign(beg,end)<br>c.assign(n,elem) <br></td>
            <td>将[beg; end)区间中的数据赋值给c。<br>将n个elem的拷贝赋值给c。</td>
        </tr>
        <tr>
            <td>c.at(idx) <br></td>
            <td>传回索引idx所指的数据，如果idx越界，抛出out_of_range。</td>
        </tr>
        <tr>
            <td>c.back() <br></td>
            <td>传回最后一个数据，不检查这个数据是否存在。</td>
        </tr>
        <tr>
            <td>c.begin() <br></td>
            <td>传回迭代器重的可一个数据。</td>
        </tr>
        <tr>
            <td>c.clear() <br></td>
            <td>移除容器中所有数据。</td>
        </tr>
        <tr>
            <td>deque&lt;Elem&gt; c<br>deque&lt;Elem&gt; c1(c2)<br>Deque&lt;Elem&gt; c(n)<br>Deque&lt;Elem&gt; c(n, elem)<br>Deque&lt;Elem&gt; c(beg,end)<br>c.~deque&lt;Elem&gt;() <br></td>
            <td>创建一个空的deque。<br>复制一个deque。<br>创建一个deque，含有n个数据，数据均已缺省构造产生。<br>创建一个含有n个elem拷贝的deque。<br>创建一个以[beg;end)区间的deque。<br>销毁所有数据，释放内存。</td>
        </tr>
        <tr>
            <td>c.empty() <br></td>
            <td>判断容器是否为空。</td>
        </tr>
        <tr>
            <td>c.end() <br></td>
            <td>指向迭代器中的最后一个数据地址。</td>
        </tr>
        <tr>
            <td>c.erase(pos)<br>c.erase(beg,end) <br></td>
            <td>删除pos位置的数据，传回下一个数据的位置。<br>删除[beg,end)区间的数据，传回下一个数据的位置。</td>
        </tr>
        <tr>
            <td>c.front() <br></td>
            <td>传回地一个数据。</td>
        </tr>
        <tr>
            <td>get_allocator <br></td>
            <td>使用构造函数返回一个拷贝。</td>
        </tr>
        <tr>
            <td>c.insert(pos,elem) <br>c.insert(pos,n,elem)<br>c.insert(pos,beg,end)<br></td>
            <td>在pos位置插入一个elem拷贝，传回新数据位置。<br>在pos位置插入&gt;n个elem数据。无返回值。<br>在pos位置插入在[beg,end)区间的数据。无返回值。</td>
        </tr>
        <tr>
            <td>c.max_size() <br></td>
            <td>返回容器中最大数据的数量。</td>
        </tr>
        <tr>
            <td>c.pop_back() <br></td>
            <td>删除最后一个数据。</td>
        </tr>
        <tr>
            <td>c.pop_front() <br></td>
            <td>删除头部数据。</td>
        </tr>
        <tr>
            <td>c.push_back(elem) <br></td>
            <td>在尾部加入一个数据。</td>
        </tr>
        <tr>
            <td>c.push_front(elem) <br></td>
            <td>在头部插入一个数据。</td>
        </tr>
        <tr>
            <td>c.rbegin() <br></td>
            <td>传回一个逆向队列的第一个数据。</td>
        </tr>
        <tr>
            <td>c.rend() <br></td>
            <td>传回一个逆向队列的最后一个数据的下一个位置。</td>
        </tr>
        <tr>
            <td>c.resize(num) <br></td>
            <td>重新指定队列的长度。</td>
        </tr>
        <tr>
            <td>c.size() <br></td>
            <td>返回容器中实际数据的个数。</td>
        </tr>
        <tr>
            <td>C1.swap(c2) <br>Swap(c1,c2)<br></td>
            <td>将c1和c2元素互换。<br>同上操作。</td>
        </tr>
    </tbody>
</table>
</div>
<br>　　Deque操作<br><br>
<div align=center>
<table cellSpacing=0 cellPadding=0 width="77%" border=1>
    <tbody>
        <tr>
            <td width="34%">函数<br></td>
            <td width="65%">描述</td>
        </tr>
        <tr>
            <td width="34%">operator[] <br></td>
            <td width="65%">返回容器中指定位置的一个引用。</td>
        </tr>
    </tbody>
</table>
</div>
<br>　　上面这些特征和vector明显相似，所以我们会提出下面的疑问。<br><br>　　问题：如果deque和vector可以提供相同功能的时候，我们使用哪一个更好呢？<br><br>　　回答：如果你要问的话，就使用vector吧。<br><br>　　或者你给个解释？<br><br>　　非常高兴你这样问，的确，这并不是无中生有的，事实上，在<a href="http://dev.qr110.com/language/c/" target=_blank>C++</a>标准里解释了这个问题，下面有一个片断：<br><br>　　vector在默认情况下是典型的使用序列的方法，对于deque，当使用插入删除操作的时候是一个更好的选择。<br><br>　　有趣的是，本文就是要非常彻底地理解这句话。<br><br>　　<strong>什么是新的？</strong><br><br>　　细读上面两张表格，你会发现和vector比较这里增加了两个函数。<br><br>　　1、c.push_front(elem) —— 在头部插入一个数据。<br><br>　　2、c.pop_front() —— 删除头部数据。<br><br>　　调用方法和c.push_back(elem)和c.pop_back()相同，这些将来会告诉我们对于deque&gt; 会非常有用，deque可以在前后加入数据。&gt;<br><br>　　<strong>缺少了什么？</strong><br><br>　　同时你也会发现相对于vector&gt; 缺少了两个函数，你将了解到deque&gt; 不需要它们。<br><br>　　1、capacity()—— 返回vector当前的容量。<br><br>　　2、reserve() —— 给指定大小的vector&gt; 分配空间。<br><br>　　这里是我们真正研究的开始，这里说明deque&gt; 和vector它们在管理内部存储的时候是完全不同的。deque是大块大块地分配内存，每次插入固定数量的数据。vector是就近分配内存（这可能不是一个坏的事情）。但我们应该关注是，vector每次增加的内存足够大的时候，在当前的内存不够的情况。下面的实验来验证deque不需要capacity()和reserve()&gt; 是非常有道理的。<br><br>　　<strong>实验一 —— 增长的容器</strong><br><br>　　目的<br><br>　　目的是通过实验来观察deque和vector在容量增长的时候有什么不同。用图形来说明它们在分配内存和执行效率上的不同。<br><br>　　描述<br><br>　　这个实验的测试程序是从一个文件中读取文本内容，每行作为一个数据使用push_back插入到deque&gt; 和vector中，通过多次读取文件来实现插入大量的数据，下面这个类就是为了测试这个内容：<br><br>
<table align=center bgColor=#d8d8d1 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=528>#include &lt;deque&gt;<br>#include &lt;fstream&gt;<br>#include &lt;string&gt;<br>#include &lt;vector&gt;<br><br>static enum modes<br>{<br>　FM_INVALID = 0,<br>　FM_VECTOR, <br>　FM_DEQUE <br>}; <br><br>class CVectorDequeTest <br>{ <br>　public:<br>　　CVectorDequeTest(); <br>　　void ReadTestFile(const char* szFile, int iMode) <br>　　{ <br>　　　char buff[0xFFFF] = {0}; <br>　　　std::ifstream inFile;<br>　　　inFile.open(szFile);<br>　　　while(!inFile.eof())<br>　　　{<br>　　　　inFile.getline(buff, sizeof(buff));<br>　　　　if(iMode == FM_VECTOR)<br>　　　　　m_vData.push_back(buff);<br>　　　　else if(iMode == FM_DEQUE)<br>　　　　　m_dData.push_back(buff);<br>　　　} <br>　　　inFile.close();<br>　　} <br>　　virtual ~CVectorDequeTest(); <br>　protected: <br>　　std::vector&lt;std::string&gt; m_vData; <br>　　std::deque&lt;std::string&gt; m_dData;<br>};</td>
        </tr>
    </tbody>
</table>
<br><br>　　结果<br><br>　　测试程序运行的平台和一些条件：<br><br>
<div align=center>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td width="32%">CPU</td>
            <td width="67%">1.8 GHz Pentium 4</td>
        </tr>
        <tr>
            <td width="32%">内存</td>
            <td width="67%">1.50 GB</td>
        </tr>
        <tr>
            <td width="32%"><a href="http://dev.qr110.com/os/" target=_blank>操作系统</a></td>
            <td width="67%">W2K-SP4</td>
        </tr>
        <tr>
            <td width="32%">文件中的行数 </td>
            <td width="67%">9874</td>
        </tr>
        <tr>
            <td width="32%">平均每行字母个数<br></td>
            <td width="67%">1755.85</td>
        </tr>
        <tr>
            <td width="32%">读文件的次数<br></td>
            <td width="67%">45</td>
        </tr>
        <tr>
            <td width="32%">总共插入的数据个数</td>
            <td width="67%">444330</td>
        </tr>
    </tbody>
</table>
</div>
<br><br>　　使用<a href="http://dev.qr110.com/os/windows/" target=_blank>Windows</a>任务管理器来记录执行效率，本程序中使用了Laurent Guinnard 的CDuration类。消耗系统资源如下图：<br><br>
<table width="90%" align=center border=0>
    <tbody>
        <tr>
            <td>
            <div align=center><img hspace=3 src="http://www.5178c.com/article/UploadPic/2006-5/2006519162222943.gif" width=500 align=center vspace=1 border=1></div>
            </td>
        </tr>
    </tbody>
</table>
<br>　　注意在vector分配内存的最高峰，vector在分配内存的时候是怎样达到最高值，deque就是这样的，它在插入数据的同时，内存直线增长，首先deque的这种内存分配单元进行回收的话，存在意想不到的后果，我们希望它的分配内存看上去和vector一样，通过上面的测试我们需要进一步的测试，现提出一个假设：假设deque分配的内存不是连续的，一定需要释放和收回内存，我们将这些假设加入后面的测试中，但是首先让我们从执行的性能外表分析一下这个实验。<br><br>　　究竟分配内存需要消耗多久？<br><br>　　注意看下面这张图片，vector在不插入数据的时候在进行寻求分配更多内存。<br><br>
<table width="90%" align=center border=0>
    <tbody>
        <tr>
            <td>
            <div align=center><img hspace=3 src="http://www.5178c.com/article/UploadPic/2006-5/2006519162222751.gif" width=500 align=center vspace=1 border=1></div>
            </td>
        </tr>
    </tbody>
</table>
<br>　　同时我们也注意到使用push_back插入一组数据消耗的时间，注意，在这里每插入一组数据代表着9874个串，平均每个串的长度是1755.85。<br><br>
<table width="90%" align=center border=0>
    <tbody>
        <tr>
            <td>
            <div align=center><img hspace=3 src="http://www.5178c.com/article/UploadPic/2006-5/2006519162223961.gif" width=500 align=center vspace=1 border=1></div>
            </td>
        </tr>
    </tbody>
</table>
</font>
<p>&#160;</p>
<strong>实验二—— vector::reserve()的资源</strong><br><br>　　目的<br><br>　　这个实验的目的是vector在加入大量数据之前调用reserve()，和deque进行比较，看它们的内存分配和执行效率怎么样？<br><br>　　描述<br><br>　　本实验中的测试基本上和实验一相同，除了在测试类的构造函数中加入下面这行代码:<br><br>
<table class=txcode align=center bgColor=#d8d8d1 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=528>m_vData.reserve(1000000);</td>
        </tr>
    </tbody>
</table>
<br>　　结果<br><br>　　测试程序运行的平台和一些条件：<br><br>
<div align=center>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td width="32%">CPU<br></td>
            <td width="67%">1.8 GHz Pentium 4</td>
        </tr>
        <tr>
            <td width="32%">内存<br></td>
            <td width="67%">1.50 GB</td>
        </tr>
        <tr>
            <td width="32%"><a href="http://dev.qr110.com/os/" target=_blank><u><font color=#0000ff>操作系统</font></u></a><br></td>
            <td width="67%">W2K-SP4</td>
        </tr>
        <tr>
            <td width="32%">文件中的行数<br></td>
            <td width="67%">9874</td>
        </tr>
        <tr>
            <td width="32%">平均每行字母个数<br></td>
            <td width="67%">1755.85</td>
        </tr>
        <tr>
            <td width="32%">读文件的次数<br></td>
            <td width="67%">70</td>
        </tr>
        <tr>
            <td width="32%">总共插入的数据个数<br></td>
            <td width="67%">691180</td>
        </tr>
    </tbody>
</table>
</div>
<br>　　使用<a href="http://dev.qr110.com/os/windows/" target=_blank><u><font color=#0000ff>Windows</font></u></a>任务管理器来记录执行效率，本程序中使用了&gt;Laurent Guinnard 的CDuration类。消耗系统资源如下图：<br><br>
<table width="90%" align=center border=0>
    <tbody>
        <tr>
            <td>
            <div align=center><img hspace=3 src="http://www.5178c.com/article/UploadPic/2006-5/2006519162223860.gif" width=500 align=center vspace=1 border=1></div>
            </td>
        </tr>
    </tbody>
</table>
<br>　　我们注意到vector不在需要分配花费多余的时间分配内存了，这是由于我们使用了reserve()对于所测试的&gt;691180个数据为我们每一次插入大量数据的时候保留了足够的内存空间，对于deque存储分配的假设，观察这个测试中的内存分配图形和上一个图形，我们需要进一步量化这个测试。<br><br>　　怎样改良内存分配的性能呢？<br><br>　　下面这个图例说明随着数据的增加，容量在增加：<br><br>
<table width="90%" align=center border=0>
    <tbody>
        <tr>
            <td>
            <div align=center><img hspace=3 src="http://www.5178c.com/article/UploadPic/2006-5/2006519162224872.gif" width=500 align=center vspace=1 border=1></div>
            </td>
        </tr>
    </tbody>
</table>
<br>　　当增加数据的时候对容量的增加在vector和deque执行效率基本一样，然而，vector在插入数据的时候有一些零星的时间消耗，看下面的图例：<br><br>
<table width="90%" align=center border=0>
    <tbody>
        <tr>
            <td>
            <div align=center><img hspace=3 src="http://www.5178c.com/article/UploadPic/2006-5/2006519162224323.gif" align=center vspace=1 border=1></div>
            </td>
        </tr>
    </tbody>
</table>
<br>　　通过统计分析vector和deque在插入平均为&gt;1755.85长度的&gt;9874个数据所花费的时间，下面是总结的表格：<br><br>
<table cellSpacing=1 cellPadding=0 align=center border=0>
    <tbody>
        <tr>
            <td width="50%"><br>Vector<br></td>
            <td width="50%"><br>Deque<br></td>
        </tr>
        <tr>
            <td>
            <div align=center>
            <table>
                <tbody>
                    <tr>
                        <td><br>Mean<br></td>
                        <td><br>0.603724814 sec<br></td>
                    </tr>
                    <tr>
                        <td><br>Maximum<br></td>
                        <td><br>0.738313000 sec<br></td>
                    </tr>
                    <tr>
                        <td><br>Minimum<br></td>
                        <td><br>0.559959000 sec<br></td>
                    </tr>
                    <tr>
                        <td><br><br>Std. Dev<br></td>
                        <td><br>0.037795736 sec<br></td>
                    </tr>
                    <tr>
                        <td><br>6-Sigma<br></td>
                        <td><br>0.226774416 sec<br></td>
                    </tr>
                </tbody>
            </table>
            </div>
            </td>
            <td>
            <div align=center>
            <table>
                <tbody>
                    <tr>
                        <td><br>Mean<br></td>
                        <td><br>0.588021114 sec <br></td>
                    </tr>
                    <tr>
                        <td><br>Maximum<br></td>
                        <td><br>0.615617000 sec<br></td>
                    </tr>
                    <tr>
                        <td><br>Minimum<br></td>
                        <td><br>0.567503000 sec<br></td>
                    </tr>
                    <tr>
                        <td><br>Std. Dev<br></td>
                        <td><br>0.009907800 sec<br></td>
                    </tr>
                    <tr>
                        <td><br>6-Sigma<br></td>
                        <td><br>0.059446800 sec<br></td>
                    </tr>
                </tbody>
            </table>
            </div>
            </td>
        </tr>
    </tbody>
</table>
<br><br>　　<strong>实验三——内存回收</strong><br><br>　　目的<br><br>　　本实验是对假设deque分配的内存不是临近的，而且很难回收进行量化测试分析。<br><br>　　描述<br><br>　　在本实验中再次用到了实验一中的代码，在调用函数中加入记录增加数据执行的效率具体入下面操作：<br><br>
<table class=txcode align=center bgColor=#d8d8d1 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=528>for(xRun=0; xRun&lt;NUMBER_OF_XRUNS; xRun++)<br>{<br>　df = new CVectorDequeTest;<br>　elapsed_time = 0;<br><br>　for(i=0; i&lt;NUMBER_OF_RUNS*xRun; i++)<br>　{<br>　　cout &lt;&lt; "Deque - Run " &lt;&lt; i &lt;&lt; " of " &lt;&lt; <br>　　NUMBER_OF_RUNS*xRun &lt;&lt; "... ";<br>　　df-&gt;ReadTestFile("F:\\huge.csv",DF_DEQUE);<br>　　deque_data.push_back(datapoint());<br>　　deque_data.back().time_to_read = df-&gt;GetProcessTime();<br>　　elapsed_time += deque_data.back().time_to_read;<br>　　deque_data.back().elapsed_time = elapsed_time;<br>　　cout &lt;&lt; deque_data.back().time_to_read &lt;&lt; " seconds\n";<br>　}<br>　vnElements.push_back(df-&gt;GetDequeSize());<br>　cout &lt;&lt; "\n\nDeleting... ";<br>　del_deque.Start();<br>　delete df;<br>　del_deque.Stop();<br>　cout &lt;&lt; del_deque.GetDuration()/1000000.0 &lt;&lt; " seconds.\n\n";<br>　vTimeToDelete.push_back(del_deque.GetDuration()/1000000.0);<br>}<br></td>
        </tr>
    </tbody>
</table>
<br>　　结果<br><br>　　本测试和上面两个实验在相同的平台上运行，除了插入的数据由&gt;9874到&gt;691180，需要插入&gt;70次，下面图例显示了&gt;deque在插入数据的时候分配内存的情况，在deque里插入了平均每个长度为&gt;1755.85的字符串。&gt;<br><br>
<table width="90%" align=center border=0>
    <tbody>
        <tr>
            <td>
            <div align=center><img hspace=3 src="http://www.5178c.com/article/UploadPic/2006-5/2006519162225632.gif" align=center vspace=1 border=1></div>
            </td>
        </tr>
    </tbody>
</table>
<br>　　尽管从几个曲线图中看到的实际消耗时间不同，但些曲线图都精确到了&gt;R2=95.15%。所给的数据点都实际背离了下表中统计的曲线图数据:<br>
<div align=center>
<table>
    <tbody>
        <tr>
            <td><br>deque Results<br></td>
        </tr>
        <tr>
            <td><br>Mean<br></td>
            <td><br>0.007089269 sec <br></td>
        </tr>
        <tr>
            <td><br>Maximum<br></td>
            <td><br>11.02838496 sec<br></td>
        </tr>
        <tr>
            <td><br>Minimum<br></td>
            <td><br>-15.25901667 sec<br></td>
        </tr>
        <tr>
            <td><br>Std. Dev<br></td>
            <td><br>3.3803636 sec<br></td>
        </tr>
        <tr>
            <td><br>6-Sigma<br></td>
            <td><br>20.2821816 sec<br></td>
        </tr>
    </tbody>
</table>
</div>
<br>　　在相同的情况下比较vector的结果是非常有意义的。下面图就是将vector和deque在相同的情况下分配内存消耗的时间比较图：<br><br>
<table width="90%" align=center border=0>
    <tbody>
        <tr>
            <td>
            <div align=center><img hspace=3 src="http://www.5178c.com/article/UploadPic/2006-5/2006519162225870.gif" align=center vspace=1 border=1></div>
            </td>
        </tr>
    </tbody>
</table>
<br>　　这些数据在这个测试中是&gt;R2=82.12%。这或许可以经过每个点反复运行得到更加优化，在这个问题中这些数据适当地标注了这些点，所给的数据点都实际背离了下表中统计的曲线图数据:<br><br>
<div align=center>
<table>
    <tbody>
        <tr>
            <td><br>vector Results<br></td>
        </tr>
        <tr>
            <td><br>Mean<br></td>
            <td><br>-0.007122715sec <br></td>
        </tr>
        <tr>
            <td><br>Maximum<br></td>
            <td><br>0.283452127 sec<br></td>
        </tr>
        <tr>
            <td><br>Minimum<br></td>
            <td><br>-0.26724459sec<br></td>
        </tr>
        <tr>
            <td><br>Std. Dev<br></td>
            <td><br>0.144572356sec<br></td>
        </tr>
        <tr>
            <td><br>6-Sigma<br></td>
            <td><br>0.867434136sec</td>
        </tr>
    </tbody>
</table>
<br><br></div>
<strong>实验四—— vector::insert() 和 deque::insert() 执行特点比较<br><br></strong>　　目的<br><br>　　deque主张使用参数为常量的insert()。但怎么样能和vector::insert()比较一下呢？本实验的目的就是比较一下vector::insert()&gt; 和 deque::insert()的工作特点。 <br><br>　　描述<br><br>　　在容器的容器多次插入数据，在这里可能不符合你的需求，既然这样你可以使用insert()，试验代码也和实验一基本一样，使用insert()代替push_back()，使用insert(&gt;)来测试。<br><br>　　结果<br><br>　　当插入常量给deque的时候，从下图可以看出和vector的对比来。<br><br>
<table width="90%" align=center border=0>
    <tbody>
        <tr>
            <td>
            <div align=center><img hspace=3 src="http://www.5178c.com/article/UploadPic/2006-5/2006519162225847.gif" width=500 align=center vspace=1 border=1></div>
            </td>
        </tr>
    </tbody>
</table>
<br>　　注意两张图片中时间轴的不同，这是将&gt;61810个数据插入到容器中。<br><br>
<table width="90%" align=center border=0>
    <tbody>
        <tr>
            <td>
            <div align=center><img hspace=3 src="http://www.5178c.com/article/UploadPic/2006-5/2006519162226966.gif" width=500 align=center vspace=1 border=1></div>
            </td>
        </tr>
    </tbody>
</table>
<br>　　<strong>实验五——读取容器的性能</strong><br><br>　　目的<br><br>　　这个实验将测试vector::at(),vector::operator[],deque::at()和deque::operator[]的性能。首先应该是operator[]比at（）效率要高，因为它不进行边界检查，同时也比较vector和deque。<br><br>　　描述<br><br>　　这个实验将测试中的容器有1000000个类型为std::string，每个字符串长度为1024的数据，分别使用at()和operator[]这两个操作来访问容器容器的数据，测试它们运行的时间，这个测试执行50次，统计每次执行的结果。<br><br>　　结果<br><br>　　我们看到使用vector和deque访问容器中的数据，他们执行的性能差别很小，使用operator[]和at()访问数据的性能差别几乎可以忽略不计，下面是统计的结果：<br><br>
<table cellSpacing=0 cellPadding=0 width="59%" align=center border=0>
    <tbody>
        <tr>
            <td>
            <div align=center>
            <table>
                <tbody>
                    <tr>
                        <td><br>vector::at()<br></td>
                    </tr>
                    <tr>
                        <td><br>Mean<br></td>
                        <td><br>1.177088125sec<br></td>
                    </tr>
                    <tr>
                        <td><br>Maximum<br></td>
                        <td><br>1.189580000sec<br></td>
                    </tr>
                    <tr>
                        <td><br>Minimum<br></td>
                        <td><br>1.168340000sec<br></td>
                    </tr>
                    <tr>
                        <td><br>Std. Dev<br></td>
                        <td><br>0.006495193sec<br></td>
                    </tr>
                    <tr>
                        <td><br>6-Sigma<br></td>
                        <td><br>0.038971158sec<br></td>
                    </tr>
                </tbody>
            </table>
            </div>
            </td>
            <td>
            <div align=center>
            <table>
                <tbody>
                    <tr>
                        <td><br>deque::at()<br></td>
                    </tr>
                    <tr>
                        <td><br>Mean<br></td>
                        <td><br>1.182364375sec <br></td>
                    </tr>
                    <tr>
                        <td><br>Maximum<br></td>
                        <td><br>1.226860000sec<br></td>
                    </tr>
                    <tr>
                        <td><br>Minimum<br></td>
                        <td><br>1.161270000sec<br></td>
                    </tr>
                    <tr>
                        <td><br>Std. Dev<br></td>
                        <td><br>0.016362148sec<br></td>
                    </tr>
                    <tr>
                        <td><br>6-Sigma<br></td>
                        <td><br>0.098172888sec<br></td>
                    </tr>
                </tbody>
            </table>
            </div>
            </td>
        </tr>
        <tr>
            <td>
            <div align=center>
            <table>
                <tbody>
                    <tr>
                        <td><br>vector::operator[]<br></td>
                    </tr>
                    <tr>
                        <td><br>Mean<br></td>
                        <td><br>1.164221042sec<br></td>
                    </tr>
                    <tr>
                        <td><br>Maximum<br></td>
                        <td><br>1.192550000sec<br></td>
                    </tr>
                    <tr>
                        <td><br>Minimum<br></td>
                        <td><br>1.155690000sec<br></td>
                    </tr>
                    <tr>
                        <td><br>Std. Dev<br></td>
                        <td><br>0.007698520sec<br></td>
                    </tr>
                    <tr>
                        <td><br>6-Sigma<br></td>
                        <td><br>0.046191120sec<br></td>
                    </tr>
                </tbody>
            </table>
            </div>
            </td>
            <td>
            <div align=center>
            <table>
                <tbody>
                    <tr>
                        <td><br>deque::operator[]<br></td>
                    </tr>
                    <tr>
                        <td><br>Mean<br></td>
                        <td><br>1.181507292sec <br></td>
                    </tr>
                    <tr>
                        <td><br>Maximum<br></td>
                        <td><br>1.218540000 sec<br></td>
                    </tr>
                    <tr>
                        <td><br>Minimum<br></td>
                        <td><br>1.162710000sec<br></td>
                    </tr>
                    <tr>
                        <td><br>Std. Dev<br></td>
                        <td><br>0.010275712sec<br></td>
                    </tr>
                    <tr>
                        <td><br>6-Sigma<br></td>
                        <td><br>0.061654272sec<br></td>
                    </tr>
                </tbody>
            </table>
            </div>
            </td>
        </tr>
    </tbody>
</table>
<br>　　<strong>结论</strong><br><br>　　在这篇文章中我们覆盖了多种不同的情况来选择我们到底是该使用vector还是deque。让我们总结一下测试的结果看下面几个结论。<br><br>　　当执行大数据量的调用push_back()的时候，记住要调用vector::reserve()。<br><br>　　在实验一中我们研究了vector和deque在插入数据的情况。通过这些假设，我们可以看出deque分配的空间是预先分配好的，deque维持一个固定增长率，在vector实验中我们考虑到应该调用vecor::reserve()&gt;.然后在下面这个例子验证了我们的假设，在使用vector的时候调用reserve()能够膀子我们预先分配空间，这将是vector一个默认选择的操作。<br><br>　　当你分配很多内存单元的时候，记住使用deque回收内存要比vector消耗时间多。<br><br>　　在实验三中我们探讨了vector和deque在回收非邻接内存块上的不同，分别证明了vector在分配内存的时候是线性增长，而deque是指数增长，同样，vector要回收的内存比deque多的多，如果你循环调用了push_back()，那么deque将获取大量的内存，而且是临近的。我们通过测试发现在分配内存单元消耗的时间和vector的时间接近。<br><br>　　如果你计划使用insert()，或者需要pop_front()，那就使用deque。<br><br>　　由于vector没有提供pop_front()函数，但在实验四的结果中可以看出没有insert()是非常好的，同时也告诉我们为什么deque在STL类中要作为单独的一个类划分出来。<br><br>　　对于访问数据，vector::at()效率最高。<br><br>　　在实验五中统计的数据表示，所有访问数据方法的效率是非常接近的，但是vector::at()效率最高。这是因为最优的平衡图访问时间为最低的六个西格玛值。<br><br>　　<strong>最后</strong><br><br>　　我希望本文能够带你认识deque，而且对它感兴趣或者一个启发，欢迎继续讨论关于vector和deque任何问题和内容。
<img src ="http://www.cppblog.com/tyt2008cn/aggbug/43497.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tyt2008cn/" target="_blank">微尘</a> 2008-02-29 22:04 <a href="http://www.cppblog.com/tyt2008cn/archive/2008/02/29/43497.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>