chap04.htm.kbk

来自「c++设计思想」· KBK 代码 · 共 1,135 行 · 第 1/5 页

KBK
1,135
字号
 color=#004488>"vector"</font>);
  testSwap&lt;deque&lt;Noisy&gt; &gt;(<font color=#004488>"deque"</font>);
  testSwap&lt;list&lt;Noisy&gt; &gt;(<font color=#004488>"list"</font>);
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When you run this, you&#8217;ll discover
that each type of sequence container is able to swap one sequence for another
without any copying or assignments, even if the sequences are of different
sizes. In effect, you&#8217;re completely swapping the memory of one object for
another.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The STL algorithms also contain a
<B>swap(&#160;)</B>, and when this function is applied to two containers of the
same type, it will use the member <B>swap(&#160;)</B> to achieve fast
performance. Consequently, if you apply the <B>sort(&#160;)</B> algorithm to a
container of containers, you will find that the performance is very fast &#8211;
it turns out that fast sorting of a container of containers was a design goal of
the STL.</FONT><A NAME="_Toc519042032"></A><BR></P></DIV>
<A NAME="Heading220"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
Robustness of lists</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">To break a <B>list</B>, you have to work
pretty hard:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C07:ListRobustness.cpp</font>
<font color=#009900>// lists are harder to break</font>
<font color=#009900>//{L} ../TestSuite/Test</font>
#include &lt;list&gt;
#include &lt;iostream&gt;
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;

<font color=#0000ff>int</font> main() {
  list&lt;<font color=#0000ff>int</font>&gt; li(100, 0);
  list&lt;<font color=#0000ff>int</font>&gt;::iterator i = li.begin();
  <font color=#0000ff>for</font>(<font color=#0000ff>int</font> j = 0; j &lt; li.size() / 2; j++)
    i++;
  <font color=#009900>// Walk the iterator forward as you perform </font>
  <font color=#009900>// a lot of insertions in the middle:</font>
  <font color=#0000ff>for</font>(<font color=#0000ff>int</font> k = 0; k &lt; 1000; k++)
    li.insert(i++, 1); <font color=#009900>// No problem</font>
  li.erase(i);
  i++;
  <font color=#009900>//! *i = 2; // Oops! It's invalid</font>
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When the link that the iterator <B>i</B>
was pointing to was erased, it was unlinked from the list and thus became
invalid. Trying to move forward to the &#8220;next link&#8221; from an invalid
link is poorly-formed code. Notice that the operation that broke <B>deque</B> in
<B>DequeCoreDump.cpp</B> is perfectly fine with a
<B>list</B>.</FONT><A NAME="_Toc519042033"></A><BR></P></DIV>
<A NAME="Heading221"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H2 ALIGN="LEFT">
Performance comparison</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">To get a better feel for the differences
between the sequence containers, it&#8217;s illuminating to race them against
each other while performing various operations. </FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C07:SequencePerformance.cpp</font>
<font color=#009900>// Comparing the performance of the basic</font>
<font color=#009900>// sequence containers for various operations</font>
<font color=#009900>//{L} ../TestSuite/Test</font>
#include &lt;vector&gt;
#include &lt;queue&gt;
#include &lt;list&gt;
#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;typeinfo&gt;
#include &lt;ctime&gt;
#include &lt;cstdlib&gt;
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;

<font color=#0000ff>class</font> FixedSize {
  <font color=#0000ff>int</font> x[20];
  <font color=#009900>// Automatic generation of default constructor,</font>
  <font color=#009900>// copy-constructor and operator=</font>
} fs;

<font color=#0000ff>template</font>&lt;<font color=#0000ff>class</font> Cont&gt;
<font color=#0000ff>struct</font> InsertBack {
  <font color=#0000ff>void</font> <font color=#0000ff>operator</font>()(Cont&amp; c, <font color=#0000ff>long</font> count) {
    <font color=#0000ff>for</font>(<font color=#0000ff>long</font> i = 0; i &lt; count; i++)
      c.push_back(fs);
  }
  <font color=#0000ff>char</font>* testName() { <font color=#0000ff>return</font> <font color=#004488>"InsertBack"</font>; }
};

<font color=#0000ff>template</font>&lt;<font color=#0000ff>class</font> Cont&gt;
<font color=#0000ff>struct</font> InsertFront {
  <font color=#0000ff>void</font> <font color=#0000ff>operator</font>()(Cont&amp; c, <font color=#0000ff>long</font> count) {
    <font color=#0000ff>long</font> cnt = count * 10;
    <font color=#0000ff>for</font>(<font color=#0000ff>long</font> i = 0; i &lt; cnt; i++)
      c.push_front(fs);
  }  
  <font color=#0000ff>char</font>* testName() { <font color=#0000ff>return</font> <font color=#004488>"InsertFront"</font>; }
};

<font color=#0000ff>template</font>&lt;<font color=#0000ff>class</font> Cont&gt;
<font color=#0000ff>struct</font> InsertMiddle {
  <font color=#0000ff>void</font> <font color=#0000ff>operator</font>()(Cont&amp; c, <font color=#0000ff>long</font> count) {
    <font color=#0000ff>typename</font> Cont::iterator it;
    <font color=#0000ff>long</font> cnt = count / 10;
    <font color=#0000ff>for</font>(<font color=#0000ff>long</font> i = 0; i &lt; cnt; i++) {
      <font color=#009900>// Must get the iterator every time to keep</font>
      <font color=#009900>// from causing an access violation with</font>
      <font color=#009900>// vector. Increment it to put it in the</font>
      <font color=#009900>// middle of the container:</font>
      it = c.begin();
      it++;
      c.insert(it, fs);
    }
  }
  <font color=#0000ff>char</font>* testName() { <font color=#0000ff>return</font> <font color=#004488>"InsertMiddle"</font>; }
};

<font color=#0000ff>template</font>&lt;<font color=#0000ff>class</font> Cont&gt;
<font color=#0000ff>struct</font> RandomAccess { <font color=#009900>// Not for list</font>
  <font color=#0000ff>void</font> <font color=#0000ff>operator</font>()(Cont&amp; c, <font color=#0000ff>long</font> count) {
    <font color=#0000ff>int</font> sz = c.size();
    <font color=#0000ff>long</font> cnt = count * 100;
    <font color=#0000ff>for</font>(<font color=#0000ff>long</font> i = 0; i &lt; cnt; i++)
      c[rand() % sz];
  }
  <font color=#0000ff>char</font>* testName() { <font color=#0000ff>return</font> <font color=#004488>"RandomAccess"</font>; }
};

<font color=#0000ff>template</font>&lt;<font color=#0000ff>class</font> Cont&gt;
<font color=#0000ff>struct</font> Traversal {
  <font color=#0000ff>void</font> <font color=#0000ff>operator</font>()(Cont&amp; c, <font color=#0000ff>long</font> count) {
    <font color=#0000ff>long</font> cnt = count / 100;
    <font color=#0000ff>for</font>(<font color=#0000ff>long</font> i = 0; i &lt; cnt; i++) {
      <font color=#0000ff>typename</font> Cont::iterator it = c.begin(),
        end = c.end();
      <font color=#0000ff>while</font>(it != end) it++;
    }
  }
  <font color=#0000ff>char</font>* testName() { <font color=#0000ff>return</font> <font color=#004488>"Traversal"</font>; }
};

<font color=#0000ff>template</font>&lt;<font color=#0000ff>class</font> Cont&gt;
<font color=#0000ff>struct</font> Swap {
  <font color=#0000ff>void</font> <font color=#0000ff>operator</font>()(Cont&amp; c, <font color=#0000ff>long</font> count) {
    <font color=#0000ff>int</font> middle = c.size() / 2;
    <font color=#0000ff>typename</font> Cont::iterator it = c.begin(), 
      mid = c.begin();
    it++; <font color=#009900>// Put it in the middle</font>
    <font color=#0000ff>for</font>(<font color=#0000ff>int</font> x = 0; x &lt; middle + 1; x++)
      mid++;
    <font color=#0000ff>long</font> cnt = count * 10;
    <font color=#0000ff>for</font>(<font color=#0000ff>long</font> i = 0; i &lt; cnt; i++)
      swap(*it, *mid);
  }
  <font color=#0000ff>char</font>* testName() { <font color=#0000ff>return</font> <font color=#004488>"Swap"</font>; }
};

<font color=#0000ff>template</font>&lt;<font color=#0000ff>class</font> Cont&gt;
<font color=#0000ff>struct</font> RemoveMiddle {
  <font color=#0000ff>void</font> <font color=#0000ff>operator</font>()(Cont&amp; c, <font color=#0000ff>long</font> count) {
    <font color=#0000ff>long</font> cnt = count / 10;
    <font color=#0000ff>if</font>(cnt &gt; c.size()) {
      cout &lt;&lt; <font color=#004488>"RemoveMiddle: not enough elements"</font>
        &lt;&lt; endl;
      <font color=#0000ff>return</font>;
    }
    <font color=#0000ff>for</font>(<font color=#0000ff>long</font> i = 0; i &lt; cnt; i++) {
      <font color=#0000ff>typename</font> Cont::iterator it = c.begin();
      it++;
      c.erase(it);
    }
  }
  <font color=#0000ff>char</font>* testName() { <font color=#0000ff>return</font> <font color=#004488>"RemoveMiddle"</font>; }
};

<font color=#0000ff>template</font>&lt;<font color=#0000ff>class</font> Cont&gt;
<font color=#0000ff>struct</font> RemoveBack {
  <font color=#0000ff>void</font> <font color=#0000ff>operator</font>()(Cont&amp; c, <font color=#0000ff>long</font> count) {
    <font color=#0000ff>long</font> cnt = count * 10;
    <font color=#0000ff>if</font>(cnt &gt; c.size()) {
      cout &lt;&lt; <font color=#004488>"RemoveBack: not enough elements"</font>
        &lt;&lt; endl;
      <font color=#0000ff>return</font>;
    }
    <font color=#0000ff>for</font>(<font color=#0000ff>long</font> i = 0; i &lt; cnt; i++)
      c.pop_back();
  }
  <font color=#0000ff>char</font>* testName() { <font color=#0000ff>return</font> <font color=#004488>"RemoveBack"</font>; }
};

<font color=#0000ff>template</font>&lt;<font color=#0000ff>class</font> Op, <font color=#0000ff>class</font> Container&gt;
<font color=#0000ff>void</font> measureTime(Op f, Container&amp; c, <font color=#0000ff>long</font> count){
  string id(<font color=#0000ff>typeid</font>(f).name());
  <font color=#0000ff>bool</font> Deque = id.find(<font color=#004488>"deque"</font>) != string::npos;
  <font color=#0000ff>bool</font> List = id.find(<font color=#004488>"list"</font>) != string::npos;
  <font color=#0000ff>bool</font> Vector = id.find(<font color=#004488>"vector"</font>) !=string::npos;
  string cont = Deque ? <font color=#004488>"deque"</font> : List ? <font color=#004488>"list"</font> 
    : Vector? <font color=#004488>"vector"</font> : <font color=#004488>"unknown"</font>;
  cout &lt;&lt; f.testName() &lt;&lt; <font color=#004488>" for "</font> &lt;&lt; cont &lt;&lt; <font color=#004488>": "</font>;
  <font color=#009900>// Standard C library CPU ticks:</font>
  clock_t ticks = clock();
  f(c, count); <font color=#009900>// Run the test</font>
  ticks = clock() - ticks;
  cout &lt;&lt; ticks &lt;&lt; endl;
}

<font color=#0000ff>typedef</font> deque&lt;FixedSize&gt; DF;
<font color=#0000ff>typedef</font> list&lt;FixedSize&gt; LF;
<font color=#0000ff>typedef</font> vector&lt;FixedSize&gt; VF;

<font color=#0000ff>int</font> main(<font color=#0000ff>int</font> argc, <font color=#0000ff>char</font>* argv[]) {
  srand(time(0));
  <font color=#0000ff>long</font> count = 1000;
  <font color=#0000ff>if</font>(argc &gt;= 2) count = atoi(argv[1]);
  DF deq;
  LF lst;
  VF vec, vecres;
  vecres.reserve(count); <font color=#009900>// Preallocate storage</font>
  measureTime(InsertBack&lt;VF&gt;(), vec, count);
  measureTime(InsertBack&lt;VF&gt;(), vecres, count);
  measureTime(InsertBack&lt;DF&gt;(), deq, count);
  measureTime(InsertBack&lt;LF&gt;(), lst, count);
  <font color=#009900>// Can't push_front() with a vector:</font>
<font color=#009900>//! measureTime(InsertFront&lt;VF&gt;(), vec, count);</font>
  measureTime(InsertFront&lt;DF&gt;(), deq, count);
  measureTime(InsertFront&lt;LF&gt;(), lst, count);
  measureTime(InsertMiddle&lt;VF&gt;(), vec, count);
  measureTime(InsertMiddle&lt;DF&gt;(), deq, count);
  measureTime(InsertMiddle&lt;LF&gt;(), lst, count);
  measureTime(RandomAccess&lt;VF&gt;(), vec, count);
  measureTime(RandomAccess&lt;DF&gt;(), deq, count);
  <font color=#009900>// Can't operator[] with a list:</font>
<font color=#009900>//! measureTime(RandomAccess&lt;LF&gt;(), lst, count);</font>
  measureTime(Traversal&lt;VF&gt;(), vec, count);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?