﻿<?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++博客-mysileng-随笔分类-STL</title><link>http://www.cppblog.com/mysileng/category/20265.html</link><description /><language>zh-cn</language><lastBuildDate>Sun, 02 Jun 2013 18:24:50 GMT</lastBuildDate><pubDate>Sun, 02 Jun 2013 18:24:50 GMT</pubDate><ttl>60</ttl><item><title>STL 中sort源码分析</title><link>http://www.cppblog.com/mysileng/archive/2013/06/01/200744.html</link><dc:creator>鑫龙</dc:creator><author>鑫龙</author><pubDate>Sat, 01 Jun 2013 10:53:00 GMT</pubDate><guid>http://www.cppblog.com/mysileng/archive/2013/06/01/200744.html</guid><wfw:comment>http://www.cppblog.com/mysileng/comments/200744.html</wfw:comment><comments>http://www.cppblog.com/mysileng/archive/2013/06/01/200744.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mysileng/comments/commentRss/200744.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mysileng/services/trackbacks/200744.html</trackback:ping><description><![CDATA[<p style="margin: 0px; padding: 0px; font-family: Arial; font-size: 14.44444465637207px; line-height: 25.981481552124023px; background-color: #ffffff; ">转自:<a href="http://blog.csdn.net/superhackerzhang/article/details/6410670">http://blog.csdn.net/superhackerzhang/article/details/6410670</a>&nbsp;<br /><br />以SGI的STL为例</p><p style="margin: 0px; padding: 0px; font-family: Arial; font-size: 14.44444465637207px; line-height: 25.981481552124023px; background-color: #ffffff; ">&nbsp;</p><p style="margin: 0px; padding: 0px; font-family: Arial; font-size: 14.44444465637207px; line-height: 25.981481552124023px; background-color: #ffffff; ">sort有两种重载形式</p><p style="margin: 0px; padding: 0px; font-family: Arial; font-size: 14.44444465637207px; line-height: 25.981481552124023px; background-color: #ffffff; ">&nbsp;</p><p style="margin: 0px; padding: 0px; font-family: Arial; font-size: 14.44444465637207px; line-height: 25.981481552124023px; background-color: #ffffff; "><span style="white-space: pre; ">template &lt;class <a href="http://blog.csdn.net/superhackerzhang/article/details/RandomAccessIterator.html" style="color: #ff9900; text-decoration: none; ">RandomAccessIterator</a>&gt;</span></p><pre style="white-space: pre-wrap; word-wrap: break-word; font-size: 14.44444465637207px; line-height: 25.981481552124023px; background-color: #ffffff; ">void sort(RandomAccessIterator first, RandomAccessIterator last);  <br />template &lt;class RandomAccessIterator, class <a href="http://blog.csdn.net/superhackerzhang/article/details/StrictWeakOrdering.html" style="color: #ff9900; text-decoration: none; ">StrictWeakOrdering</a>&gt; <br />void sort(RandomAccessIterator first, RandomAccessIterator last,StrictWeakOrdering comp);</pre><pre style="white-space: pre-wrap; word-wrap: break-word; font-size: 14.44444465637207px; line-height: 25.981481552124023px; background-color: #ffffff; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">这两种形式都要求形随机访问迭代器，因此只能用于容器vector或deque,这里我们只以第一种为例进行讲解</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">在数据量大时，采用Quick Sort，分段递归排序，一旦分段后的数据量小于门限值时，为避免递归的额外开销，便采用Insertion sort。<span style="font-size: 14.44444465637207px; line-height: 25.981481552124023px; "> </span></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">如果递归的层次过深，还会使用Heap Sort.</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">对于以下的以__开头的命名函数，表示其为被内部的其它函数调用，而不能被用户直接调用。</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">首先来看插入排序</pre> <pre style="white-space: pre-wrap; word-wrap: break-word; "><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->template&nbsp;&lt;<span style="color: #0000FF; ">class</span>&nbsp;_RandomAccessIter&gt;&nbsp;<br /><span style="color: #0000FF; ">void</span>&nbsp;__insertion_sort(_RandomAccessIter&nbsp;__first,&nbsp;_RandomAccessIter&nbsp;__last)&nbsp;{&nbsp;&nbsp;&nbsp;<br /><span style="color: #0000FF; ">  if</span>&nbsp;(__first&nbsp;==&nbsp;__last)&nbsp;<span style="color: #0000FF; ">return</span>;&nbsp;&nbsp;&nbsp;&nbsp;<br /><span style="color: #0000FF; ">  for</span>&nbsp;(_RandomAccessIter&nbsp;__i&nbsp;=&nbsp;__first&nbsp;+&nbsp;1;&nbsp;__i&nbsp;!=&nbsp;__last;&nbsp;++__i)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />    __linear_insert(__first,&nbsp;__i,&nbsp;__VALUE_TYPE(__first));&nbsp;}</div></pre> <pre style="white-space: pre-wrap; word-wrap: break-word; ">其所调用的 __linear_insert如下示：</pre><pre style="white-space: pre-wrap; word-wrap: break-word; "><pre style="white-space: pre-wrap; word-wrap: break-word; "><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"> <pre style="font-size: 14px; background-color: #ffffff; white-space: pre-wrap; word-wrap: break-word; ">template &lt;class _RandomAccessIter, class _Tp&gt;</pre>inline&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;__linear_insert(_RandomAccessIter&nbsp;__first,&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_RandomAccessIter&nbsp;__last,&nbsp;_Tp*)&nbsp;{<br />&nbsp;&nbsp;_Tp&nbsp;__val&nbsp;=&nbsp;*__last;<br />&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(__val&nbsp;&lt;&nbsp;*__first)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;copy_backward(__first,&nbsp;__last,&nbsp;__last&nbsp;+&nbsp;1);<br />&nbsp;&nbsp;&nbsp;&nbsp;*__first&nbsp;=&nbsp;__val;<br />&nbsp;&nbsp;}<span style="color: #0000FF; ">else</span><br />&nbsp;&nbsp;&nbsp;&nbsp;__unguarded_linear_insert(__last,&nbsp;__val);<br />}</div></pre> <pre style="white-space: pre-wrap; word-wrap: break-word; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">这里需要对其进行一下说明，通常情况下在进行插入排序时，既要进行大小的比较，又要对边界进行控制，经过上面的改进后，但只需要进<span style="font-size: 14.44444465637207px; line-height: 25.981481552124023px; ">行大小的比较便可，这就是代码的高明这处。</span></pre> <span style="font-size: 14.44444465637207px; line-height: 25.981481552124023px; ">首先对要插入有序部分的元素__val与队首的最小元素 *__first进行比较，如果__val &lt; *__first，则只__first与 __last之间的元素向后移一个</span><span style="font-size: 14.44444465637207px; line-height: 25.981481552124023px; ">位置，然后将__val插入队首。</span><span style="font-size: 14.44444465637207px; line-height: 25.981481552124023px; "><br /></span> <span style="font-size: 14.44444465637207px; line-height: 25.981481552124023px; ">如果__val &gt;= *__first，则说明__val在将要新生成的有序队列中不是最小，因此，在下面的while中不用进行界限控制，只比较元素的大小</span><span style="font-size: 14.44444465637207px; line-height: 25.981481552124023px; ">即可。</span><span style="font-size: 14.44444465637207px; line-height: 25.981481552124023px; "><br /></span> </pre></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">template &lt;class _RandomAccessIter, class _Tp&gt; <br />void __unguarded_linear_insert(_RandomAccessIter __last, _Tp __val) {   <br />  _RandomAccessIter __next = __last;  <br />   --__next;   <br />   while (__val &lt; *__next) {     <br />     *__last = *__next;     <br />     __last = __next;     <br />     --__next;  <br />   }   <br />   *__last = __val; <br />}</pre> <pre style="white-space: pre-wrap; word-wrap: break-word; ">在STL中对避免快排时每次都选择最小或最大的元素做轴，使用以下函数选择一个三点中值。</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">template &lt;class _Tp&gt; <br />inline const _Tp&amp; __median(const _Tp&amp; __a, const _Tp&amp; __b, const _Tp&amp; __c) {   <br />  __STL_REQUIRES(_Tp, _LessThanComparable);   <br />  if (__a &lt; __b)     <br />    if (__b &lt; __c)       return __b;     <br />    else if (__a &lt; __c)       return __c;     <br />    else       return __a;   <br />  else if (__a &lt; __c)     return __a;   <br />  else if (__b &lt; __c)     return __c;   <br />  else     return __b; <br />}</pre> <pre style="white-space: pre-wrap; word-wrap: break-word; ">下面是快排中所要使用的分割函数。对[first,last)区间的元素进行分割，使用得中轴右边的元素大于等于中轴，左边的元素小于等于中轴，<span style="font-size: 14.44444465637207px; line-height: 25.981481552124023px; ">并返回中轴所在位置。</span></pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">template &lt;class _RandomAccessIter, class _Tp&gt; <br />_RandomAccessIter __unguarded_partition(_RandomAccessIter __first,_RandomAccessIter __last,_Tp __pivot) {   <br />   while (true) {     <br />     while (*__first &lt; __pivot)       ++__first;     <br />     --__last;     <br />     while (__pivot &lt; *__last)       --__last;     <br />     if (!(__first &lt; __last))       <br />       return __first;     <br />     iter_swap(__first, __last);     <br />     ++__first;  <br />    } <br />}    </pre> <pre style="white-space: pre-wrap; word-wrap: break-word; ">sort 代码如下</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">template &lt;class _RandomAccessIter&gt; <br />inline void sort(_RandomAccessIter __first, _RandomAccessIter __last) {            <br />  if (__first != __last) {     <br />    __introsort_loop(__first, __last,                      <br />                     __VALUE_TYPE(__first),                      <br />                     __lg(__last - __first) * 2);     <br />                     __final_insertion_sort(__first, __last);   <br />   } <br />}</pre> <pre style="white-space: pre-wrap; word-wrap: break-word; ">基中__lg(n)用来找出2^k&lt;=n的最大k值，用以控控制递归的深度。</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">template &lt;class _Size&gt; <br />inline _Size __lg(_Size __n) {   <br />  _Size __k;   <br />  for (__k = 0; __n != 1; __n &gt;&gt;= 1) ++__k;   <br />  return __k; <br />}</pre> <pre style="white-space: pre-wrap; word-wrap: break-word; ">下面的是用来对区间使用快排，以达到部分有序状态。</pre> <pre style="white-space: pre-wrap; word-wrap: break-word; ">template &lt;class _RandomAccessIter, class _Tp, class _Size&gt; <br />void __introsort_loop(_RandomAccessIter __first,                       <br />                      _RandomAccessIter __last, _Tp*,                       <br />                      _Size __depth_limit) {   <br />  while (__last - __first &gt; __stl_threshold) {//__stl_threshold在这里用前面定义的常量16，当区间多于16个元素时，才有必要使用快排。<br />     if (__depth_limit == 0) {//当递归的层次过深时，使用堆排序。       <br />       partial_sort(__first, __last, __last);       <br />       return;     <br />     }     <br />     --__depth_limit;     <br />     _RandomAccessIter __cut =       __unguarded_partition(__first, __last,                             <br />                                                           _Tp(__median(*__first,                                         <br />                                                           *(__first + (__last - __first)/2),                                          <br />                                                           *(__last - 1))));//使用分割函数，反回中轴     <br />      __introsort_loop(__cut, __last, (_Tp*) 0, __depth_limit);//对右半部分进行递归排序     <br />      __last = __cut;//使尾指针指向中轴，即要对左半部分排序   <br />    } <br />}</pre> <pre style="white-space: pre-wrap; word-wrap: break-word; ">最后使用插入排序对各部分进行排序。</pre> <pre style="white-space: pre-wrap; word-wrap: break-word; ">template &lt;class _RandomAccessIter&gt; <br />void __final_insertion_sort(_RandomAccessIter __first,                              <br />                            _RandomAccessIter __last) {   <br />  if (__last - __first &gt; __stl_threshold) {     <br />      __insertion_sort(__first, __first + __stl_threshold);     <br />      __unguarded_insertion_sort(__first + __stl_threshold, __last);   <br />  }   else     __insertion_sort(__first, __last); <br />}</pre> <pre style="white-space: pre-wrap; word-wrap: break-word; ">些函数先判断元素个数是否大于16，如是大于，则先用__insertion_sort()对16个元素的子序列排序，再用__unguarded_insertion_sort()对</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">其余的排序。否则直接用__insertion_sort()排序。</pre> <pre style="white-space: pre-wrap; word-wrap: break-word; ">template &lt;class _RandomAccessIter&gt; <br />inline void __unguarded_insertion_sort(_RandomAccessIter __first,                                  <br />                                       _RandomAccessIter __last) {   <br />  __unguarded_insertion_sort_aux(__first, __last, __VALUE_TYPE(__first)); <br />}  <br /><br />template &lt;class _RandomAccessIter, class _Tp, class _Compare&gt; <br />void __unguarded_insertion_sort_aux(_RandomAccessIter __first,<br />                                    _RandomAccessIter __last,                                     <br />                                    _Tp*, _Compare __comp) {   <br />  for (_RandomAccessIter __i = __first; __i != __last; ++__i)    <br />    __unguarded_linear_insert(__i, _Tp(*__i), __comp); <br />}</pre> <pre style="white-space: pre-wrap; word-wrap: break-word; ">template &lt;class _RandomAccessIter, class _Tp&gt; <br />void __unguarded_linear_insert(_RandomAccessIter __last, _Tp __val) {   <br />  _RandomAccessIter __next = __last;   <br />  --__next;   <br />  while (__val &lt; *__next) {     <br />    *__last = *__next;     <br />    __last = __next;     <br />    --__next;   <br />  }   <br />  *__last = __val; <br />}</pre> <pre style="white-space: pre-wrap; word-wrap: break-word; ">ps:个人感觉__final_insertion_sort()中区分区间大小是多此一举，因为最终其调用的都是__unguarded_linear_insert()，其并没用针对不</pre><pre style="white-space: pre-wrap; word-wrap: break-word; ">同的大小区间采用明显不用的算法。</pre></pre><img src ="http://www.cppblog.com/mysileng/aggbug/200744.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mysileng/" target="_blank">鑫龙</a> 2013-06-01 18:53 <a href="http://www.cppblog.com/mysileng/archive/2013/06/01/200744.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>STL中mem_fun和mem_fun_ref的用法及区别(转)</title><link>http://www.cppblog.com/mysileng/archive/2012/12/25/196615.html</link><dc:creator>鑫龙</dc:creator><author>鑫龙</author><pubDate>Tue, 25 Dec 2012 09:06:00 GMT</pubDate><guid>http://www.cppblog.com/mysileng/archive/2012/12/25/196615.html</guid><wfw:comment>http://www.cppblog.com/mysileng/comments/196615.html</wfw:comment><comments>http://www.cppblog.com/mysileng/archive/2012/12/25/196615.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mysileng/comments/commentRss/196615.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mysileng/services/trackbacks/196615.html</trackback:ping><description><![CDATA[<p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; "><strong>引子:</strong></p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; ">怎么对容器中的所有对象都进行同一个操作？我们可能首先想到的是用循环来实现。<br />比如有如下的一个类：</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; ">class ClxECS{<br />public:<br />&nbsp;&nbsp;&nbsp; int DoSomething() {&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;cout &lt;&lt; "Output from method DoSomething!" &lt;&lt; endl; // 这里以输出一句话来代替具体的操作<br />&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br />&nbsp;&nbsp;&nbsp; };<br />};</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; "><br />现在定义如下一个vector：</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; ">vector&lt;ClxECS*&gt; vECS;</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; ">for(int i = 0; i &lt; 13; i++){<br />&nbsp;&nbsp;&nbsp; ClxECS *pECS = new ClxECS;<br />&nbsp;&nbsp;&nbsp; vECS.push_back(pECS);<br />}</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; "><br />&nbsp;如果要对容器vECS中的所有对象都进行DoSomething()的操作，那么下面的循环可能是首先想到的方案：</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; ">for(int i = 0; i &lt; vECS.size(); i++)<br />&nbsp;&nbsp;&nbsp; vECS.at(i)-&gt;DoSomething();<br />&nbsp;&nbsp;&nbsp;</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; ">&nbsp;当然，我们也可以用iterator：</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; ">for(vector&lt;ClxECS*&gt;::iterator it = vECS.begin(); it != vECS.end(); ++it)<br />&nbsp;&nbsp;&nbsp; (*it)-&gt;DoSomething();</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; "><br />&nbsp;但是，有很多C++的高手和牛人们都会给我们一个忠告，那就是：在处理STL里面的容器的时候，尽量不要自己写循环。<br />那么，我们就只好用STL算法里面的for_each了。<br />首先，添加如下一个函数：</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; ">int DoSomething(ClxECS *pECS)<br />{<br />&nbsp;&nbsp;&nbsp; return pECS-&gt;DoSomething();<br />}<br />然后就可以用for_each来实现我们想要的功能：</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; ">for_each(vECS.begin(), vECS.end(), &amp;DoSomething);<br />说了半天，似乎跟mem_fun和mem_fun_ref没有什么关系。其实，说那么多都是为了引出mem_fun和mem_fun_ref。在用for_each的时候，如果我们不添加上面的那个函数，该怎么办呢？</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; "><br />这个时候就该mem_fun和mem_fun_ref隆重登场了。用如下这一行代码就行了：</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; "><strong>for_each(vECS.begin(), vECS.end(), mem_fun(&amp;ClxECS::DoSomething));</strong><br />实际上就是由迭代器去调用成员函数.</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; ">&nbsp;</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; "><strong>例子:</strong></p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; ">一</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; ">list&lt;Widget *&gt; lpw;<br />for_each(lpw.begin(), lpw.end(),mem_fun(&amp;Widget::test)); // pw-&gt;test();</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; ">二</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; ">vector&lt;Widget&gt; vw;<br />for_each(vw.begin(), vw.end(),mem_fun_ref(&amp;Widget::test)); // w.test();</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; ">三</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; ">成员函数有参数的情况：将值传入，再bind1st为this</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; ">std::for_each(m_erased.begin(), m_erased.end(),std::bind1st(std::mem_fun(&amp;SocketSet::_replace_with_last), this));<br />//相当于this-&gt;_replace_with_last(iter)&nbsp; //iter</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; "><strong>两者区别:</strong><br />mem_fun_ref的作用和用法跟mem_fun一样，唯一的不同就是：</p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; "><strong>当容器中存放的是对象实体的时候用mem_fun_ref，</strong></p><p style="margin: 0px; padding: 0px; color: #454545; font-family: Tahoma, Helvetica, Arial, STHeiti; background-color: #ffffff; "><strong>当容器中存放的是对象的指针的时候用mem_fun。<br /></strong></p><img src ="http://www.cppblog.com/mysileng/aggbug/196615.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mysileng/" target="_blank">鑫龙</a> 2012-12-25 17:06 <a href="http://www.cppblog.com/mysileng/archive/2012/12/25/196615.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>迭代器特性(iterator_traits) (转)</title><link>http://www.cppblog.com/mysileng/archive/2012/12/24/196580.html</link><dc:creator>鑫龙</dc:creator><author>鑫龙</author><pubDate>Mon, 24 Dec 2012 13:38:00 GMT</pubDate><guid>http://www.cppblog.com/mysileng/archive/2012/12/24/196580.html</guid><wfw:comment>http://www.cppblog.com/mysileng/comments/196580.html</wfw:comment><comments>http://www.cppblog.com/mysileng/archive/2012/12/24/196580.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mysileng/comments/commentRss/196580.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mysileng/services/trackbacks/196580.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp; &nbsp; &nbsp; &nbsp;本文的技术可以参考本博客: &nbsp;Traits 技术 --- 模板元编程 (转)&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; 迭代器可以区分为不同的类型，每个类型都有特定的迭代器功能。&nbsp; &nbsp; &nbsp; &nbsp; 根据迭代器类型，将算法根据类型的不同实现出更加有效率的版本，将会很...&nbsp;&nbsp;<a href='http://www.cppblog.com/mysileng/archive/2012/12/24/196580.html'>阅读全文</a><img src ="http://www.cppblog.com/mysileng/aggbug/196580.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mysileng/" target="_blank">鑫龙</a> 2012-12-24 21:38 <a href="http://www.cppblog.com/mysileng/archive/2012/12/24/196580.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++标准程序库----p258----vector迭代器的递增和递减解析</title><link>http://www.cppblog.com/mysileng/archive/2012/12/23/196551.html</link><dc:creator>鑫龙</dc:creator><author>鑫龙</author><pubDate>Sun, 23 Dec 2012 14:18:00 GMT</pubDate><guid>http://www.cppblog.com/mysileng/archive/2012/12/23/196551.html</guid><wfw:comment>http://www.cppblog.com/mysileng/comments/196551.html</wfw:comment><comments>http://www.cppblog.com/mysileng/archive/2012/12/23/196551.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mysileng/comments/commentRss/196551.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mysileng/services/trackbacks/196551.html</trackback:ping><description><![CDATA[&nbsp; &nbsp; &nbsp;问题的由来：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->vector&lt;int&gt; coll;<br />.....<br />sort(++coll.begin(),coll.end());</div>&nbsp; &nbsp; 对于sort那句，如果vecotor的底层是用指针实现（通常就是用指针实现），那么编译无法通过。<br />&nbsp; &nbsp;<br />&nbsp; &nbsp; 其实此次问题该系列上一次文章类似&lt;&lt;<a href="http://www.cppblog.com/mysileng/archive/2012/12/16/196353.html">c++标准程序库----p55----为什么需要auto_ptr_ref? (转)</a>&gt;&gt;,都是临时对象惹的祸。<br />&nbsp; &nbsp;c++不允许任何修改基本类型(包括指针)临时值的行为，但对于类类型则允许。怎么理解呢？举个例子:<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#include&nbsp;&lt;iostream&gt;<br /><span style="color: #0000FF; ">using</span>&nbsp;<span style="color: #0000FF; ">namespace</span>&nbsp;std;<br />&nbsp;<br />&nbsp;<br /><span style="color: #0000FF; ">class</span>&nbsp;node<br />{<br />&nbsp;<br /><span style="color: #0000FF; ">public</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;node(<span style="color: #0000FF; ">int</span>&nbsp;j&nbsp;=&nbsp;0):i(j){}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;i;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;<span style="color: #0000FF; ">operator</span>++()<span style="color: #008000; ">//</span><span style="color: #008000; ">这里重定义一个赋值操作符=,为下面的赋值做准备。</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i++;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />};<br />&nbsp;<br />node&nbsp;fun()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;node&nbsp;temp(1);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;temp;<span style="color: #008000; ">//</span><span style="color: #008000; ">这里返回一个类的临时变量</span><span style="color: #008000; "><br /></span>}<br />&nbsp;<br /><span style="color: #0000FF; ">int</span>*&nbsp;fun2()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;a&nbsp;=1;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>*&nbsp;b&nbsp;=&nbsp;&amp;a;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">这里返回存在栈中局部变量的地址是不对的，但只是做实验！&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;b;<span style="color: #008000; ">//</span><span style="color: #008000; ">这里返回一个普通int临时变量</span><span style="color: #008000; "><br /></span>&nbsp;<br />}<br /><span style="color: #0000FF; ">int</span>&nbsp;main()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;++fun();&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;ok!</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;++fun2();&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">这句无法通过编译&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;system("pause");<br />&nbsp;<br />}</div>&nbsp; &nbsp; 上面的例子fun()返回类类型的临时变量可以被修改，但fun2()返回的指针的临时变量不能被修改。<br />&nbsp; &nbsp; 回到开始的例子,因为vector的迭代器底层是用指针实现，所以begin()函数返回的是一个指针类型的临时变量，如果用++操作去修改，那就违反了c++的设计原则，所以无法编译通过。做到底还是左值不能被修改!!!<img src ="http://www.cppblog.com/mysileng/aggbug/196551.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mysileng/" target="_blank">鑫龙</a> 2012-12-23 22:18 <a href="http://www.cppblog.com/mysileng/archive/2012/12/23/196551.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++标准程序库----p55----为什么需要auto_ptr_ref? (转)</title><link>http://www.cppblog.com/mysileng/archive/2012/12/16/196353.html</link><dc:creator>鑫龙</dc:creator><author>鑫龙</author><pubDate>Sun, 16 Dec 2012 08:06:00 GMT</pubDate><guid>http://www.cppblog.com/mysileng/archive/2012/12/16/196353.html</guid><wfw:comment>http://www.cppblog.com/mysileng/comments/196353.html</wfw:comment><comments>http://www.cppblog.com/mysileng/archive/2012/12/16/196353.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mysileng/comments/commentRss/196353.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mysileng/services/trackbacks/196353.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 这几天开始拜读侯捷先生和孟岩先生的译作《C++标准程序库：自修教程与参考手册》&nbsp;。两位先生确实译功上乘，读得很顺。但是读到P55页关于auto_ptr_ref的讨论，却百思不得其解：为什么需要引入auto_ptr_ref这个辅助类呢？&nbsp;从书中描述来看，仿佛与拷贝构造函数&nbsp;、右值&nbsp;、类型转换&nbsp;有关。于是，结合auto_ptr的源代码，google之、...&nbsp;&nbsp;<a href='http://www.cppblog.com/mysileng/archive/2012/12/16/196353.html'>阅读全文</a><img src ="http://www.cppblog.com/mysileng/aggbug/196353.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mysileng/" target="_blank">鑫龙</a> 2012-12-16 16:06 <a href="http://www.cppblog.com/mysileng/archive/2012/12/16/196353.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>