﻿<?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++博客-紫月城游戏软件-随笔分类-C++</title><link>http://www.cppblog.com/kevinlynx/category/6337.html</link><description>低调做技术</description><language>zh-cn</language><lastBuildDate>Sat, 26 Apr 2008 04:56:01 GMT</lastBuildDate><pubDate>Sat, 26 Apr 2008 04:56:01 GMT</pubDate><ttl>60</ttl><item><title>多线程下vc2003,vc2005对虚函数表处理的BUG？</title><link>http://www.cppblog.com/kevinlynx/archive/2008/04/24/48001.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Thu, 24 Apr 2008 06:40:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2008/04/24/48001.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/48001.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2008/04/24/48001.html#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/48001.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/48001.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 考虑一下多线程代码，在设计上，App为了获取更多的功能，从Window派生，而App同时为了获取某个模块的回调(所谓的Listener)，App同时派生Listener，并将自己的指针交给另一个模块，另一个模块通过该指针多态回调到App的实现(对Listener规定的接口的implemention)。设计上只是一个很简单的Listener回调，在单线程模式下一切都很正常(后面我会罗列代码)，但是换...&nbsp;&nbsp;<a href='http://www.cppblog.com/kevinlynx/archive/2008/04/24/48001.html'>阅读全文</a><img src ="http://www.cppblog.com/kevinlynx/aggbug/48001.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2008-04-24 14:40 <a href="http://www.cppblog.com/kevinlynx/archive/2008/04/24/48001.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>调试经验总结-VC下的错误对话框</title><link>http://www.cppblog.com/kevinlynx/archive/2008/04/24/47998.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Thu, 24 Apr 2008 05:43:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2008/04/24/47998.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/47998.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2008/04/24/47998.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/47998.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/47998.html</trackback:ping><description><![CDATA[<p><font size=2>很早前就想写点总结将编程中遇到的各种错误刨根挖底地罗列出来。但是因为这些错误（VC中开调试器遇到的各种错误对话框）都是随机性的，真正想总结的时候又不想不起来有哪些错误。恰好最近运气比较背，各种错误都被我遇遍了，于是恰好有机会做个总结。 </font>
<p><font size=2>这里所说的VC下的错误对话框时指在VC中开调试器运行程序时，IDE弹出的对话框。</font>
<p><strong>1.不是错误的错误：断言</strong> .</p>
<p>将断言视为错误其实有点可笑，但是因为有些同学甚至不知道这个，所以我稍微提一下。断言对话框大致上类似于：</p>
<p><a href="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/VC_BA3E/assert_1.jpg"><img style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" height=257 alt=assert src="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/VC_BA3E/assert_thumb_1.jpg" width=444 border=0></a> </p>
<p>断言对话框是由assert引起的，在对话框上通常会给出表达式，例如assert( 0 ); 弹出对话框时就会将0这个表达式显示出来（Expression:0)。关于assert的具体信息建议自己google。这里稍微提一下一个技巧：有时候为了让assert提供更多的信息，我们可以这样写一个assert:</p>
<p>assert( expression &amp;&amp; "Function : invalid argument!" ); </p>
<p>因为字符串被用在布尔表达式中时，始终为true，不会妨碍对expression的判断，当断言发生时(expression为false) 时，断言对话框上就会显示这个字符串，从而方便我们调试。</p>
<p>要解决这个问题，首先要确定断言发生的位置，如果是你自己设置的断言被引发，就很好解决，如果是系统内部的函数产生的，那么一般是因为你传入的函数参数无效引起。</p>
<p>&nbsp;</p>
<p><strong>2.内存相关：最简单的非法访问：</strong></p>
<p>C、C++程序中经常误用无效的指针，从而大致各种各样的非法内存访问（写/读）。最简单的情况类似于：</p>
<p><a href="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/VC_BA3E/wrongaccess.jpg"><img style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" height=186 alt=wrongaccess src="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/VC_BA3E/wrongaccess_thumb.jpg" width=444 border=0></a> </p>
<p>这样的情况由类似以下代码引起：</p>
<p>char *p = 0;
<p>*p = 'a';
<p>当你看到类似于&#8220;写入位置XXXX时发生访问冲突&#8220;时，那么你大致可以断定，你的程序在某个地方访问到非法内存。开调试器对调用堆栈进行跟踪即可找出错误。</p>
<p>&nbsp;</p>
<p><strong>3.内存相关：不小心的栈上数组越界：</strong></p>
<p>当你写下类似以下的代码时：</p>
<p>char str[3];
<p>strcpy( str, "abc" );
<p>就将看到如下的对话框：
<p><a href="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/VC_BA3E/stackerror.jpg"><img style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" height=235 alt=stackerror src="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/VC_BA3E/stackerror_thumb.jpg" width=516 border=0></a>&nbsp;
<p>对话框大致的意思就是说str周围的栈被破坏了，因为str本身就被放在栈上，所以strcpy(str,"abc")多写入的'\0'就写到非法的栈区域。看到这样的对话框可以根据调用堆栈定位到错误发生的函数，然后检查此函数内部定义的数组访问，即可解决问题。
<p>&nbsp;
<p><strong>4.内存相关：不小心的堆上数组越界：<br></strong>并不是每次数组越界都会得到上面所描述的错误，当数组是在堆上分配时，情况就变得隐秘得多：
<p>char *str = new char [2];
<p>strcpy( str, "ab" ); //执行到这里时并不见得会崩溃
<p>delete [] str;//但是到这里时就肯定会崩溃
<p>以上代码导致的错误对话框还要诡异些：
<p><a href="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/VC_BA3E/heaperror.jpg"><img style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" height=206 alt=heaperror src="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/VC_BA3E/heaperror_thumb.jpg" width=516 border=0></a>
<p>似乎不同的DAMAGE对应的错误号（这里是47）都不一样，因为这里的错误发生在delete，而delete跟new很可能在不同的地方，所以这个错误调试起来不是那么容易，很多时候只能靠经验。
<p>当看到类似的对话框时，根据调用堆栈跟到delete时，你就可以大致怀疑堆上数组越界。
<p>&nbsp;
<p><strong>5.调用相关：函数调用约定带来的错误：</strong>
<p>这是所有我这里描述的错误中最诡异的一种，先看下对话框大致的样子：
<p><a href="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/VC_BA3E/run_functioncall2.jpg"><img style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" height=195 alt=run_functioncall2 src="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/VC_BA3E/run_functioncall2_thumb.jpg" width=446 border=0></a>
<p>对话框大致的意思就是说（没开调试器时对话框样式可能不一样），通过函数指针调用某个函数时，函数指针的类型（函数原型）可能与函数指针指向的函数的类型不一样。这里的类型不一致主要是调用约定(call conversation）不一样。如果函数类型（参数个数，返回值）不一样，一般不会出错。
<p>调用约定是指调用一个函数时，函数参数的压入顺序、谁来清理栈的内容等。例如默认的C、C++调用约定__cdecl，对于函数的参数是从右往左压入。而__stdcall（WIN API的调用约定）则是从左向右压。我这里所说的函数类型不一样，就是指一个函数是使用__cdecl，还是__stdcall。例如以下代码：
<p>&#160;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;__stdcall&nbsp;show(&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">str&nbsp;)&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_63_67_Open_Image onclick="this.style.display='none'; Codehighlighter1_63_67_Open_Text.style.display='none'; Codehighlighter1_63_67_Closed_Image.style.display='inline'; Codehighlighter1_63_67_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_63_67_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_63_67_Closed_Text.style.display='none'; Codehighlighter1_63_67_Open_Image.style.display='inline'; Codehighlighter1_63_67_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_63_67_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_63_67_Open_Text><span style="COLOR: #000000">{&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;__stdcall&nbsp;show2()&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_96_100_Open_Image onclick="this.style.display='none'; Codehighlighter1_96_100_Open_Text.style.display='none'; Codehighlighter1_96_100_Closed_Image.style.display='inline'; Codehighlighter1_96_100_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_96_100_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_96_100_Closed_Text.style.display='none'; Codehighlighter1_96_100_Open_Image.style.display='inline'; Codehighlighter1_96_100_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_96_100_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_96_100_Open_Text><span style="COLOR: #000000">{&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_117_239_Open_Image onclick="this.style.display='none'; Codehighlighter1_117_239_Open_Text.style.display='none'; Codehighlighter1_117_239_Closed_Image.style.display='inline'; Codehighlighter1_117_239_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_117_239_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_117_239_Closed_Text.style.display='none'; Codehighlighter1_117_239_Open_Image.style.display='inline'; Codehighlighter1_117_239_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_117_239_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_117_239_Open_Text><span style="COLOR: #000000">{&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>typedef&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">Func)(&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">);&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;show;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>Func&nbsp;my_func&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(Func)&nbsp;p;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>my_func(&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">kevin</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;);&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>&nbsp;</p>
<p>因为Func默认地被处理为__cdecl，而show是__stdcall的，所以当通过函数指针my_func时，就导致了以上对话框的出现。但是当p指向show2时，又不会出错，这是因为show2没有参数，不同的调用约定不影响这个规则。<br><br></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><strong style="mso-bidi-font-weight: normal"><span lang=EN-US>6.</span></strong><strong style="mso-bidi-font-weight: normal"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">异常相关：默认终止程序</span><span lang=EN-US><o:p></o:p></span></strong></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当我们使用</span><span lang=EN-US>C++</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">库时，因为库本身可能会抛出</span><span lang=EN-US>C++</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">异常，如果你不捕获这个异常，那么</span><span lang=EN-US>C++</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">默认就会调用</span><span lang=EN-US>abort</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（或者</span><span lang=EN-US>exit</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）函数终止程序。例如：</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;test()<br><img id=Codehighlighter1_12_61_Open_Image onclick="this.style.display='none'; Codehighlighter1_12_61_Open_Text.style.display='none'; Codehighlighter1_12_61_Closed_Image.style.display='inline'; Codehighlighter1_12_61_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_12_61_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_12_61_Closed_Text.style.display='none'; Codehighlighter1_12_61_Open_Image.style.display='inline'; Codehighlighter1_12_61_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_12_61_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_12_61_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000">&nbsp;std::exception(&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">some&nbsp;exceptions</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"></o:p></span>&nbsp;</p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当你调用</span><span lang=EN-US>test</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数时，如果不</span><span lang=EN-US>catch</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这个异常，开调试器就会得到类似的错误对话框：</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><img height=199 alt="" src="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/VC_BA3E/exception.jpg" width=443 border=0>&nbsp;</o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">而如果不开调试器，则会得到：</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p>&nbsp;<img height=232 alt="" src="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/VC_BA3E/abort.jpg" width=439 border=0></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当你看到类似于&#8220;</span><span lang=EN-US>This application has requested the Runtime to terminate it&#8230;&#8221;</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">之类的字眼时，那就表明程序调用了</span><span lang=EN-US>abort</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（或</span><span lang=EN-US>exit</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）函数，导致程序异常终止。其实这个错误只要开调试器，一般可以准确定位错误的发生点。</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p>&nbsp;</o:p></span></p>
<p>&#160;</p>
<img src ="http://www.cppblog.com/kevinlynx/aggbug/47998.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2008-04-24 13:43 <a href="http://www.cppblog.com/kevinlynx/archive/2008/04/24/47998.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>代码自动生成-宏带来的奇技淫巧</title><link>http://www.cppblog.com/kevinlynx/archive/2008/03/19/44828.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Wed, 19 Mar 2008 02:34:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2008/03/19/44828.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/44828.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2008/03/19/44828.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/44828.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/44828.html</trackback:ping><description><![CDATA[<p style="FONT-SIZE: 10pt">Author : Kevin Lynx</p>
<p style="FONT-SIZE: 10pt">众多C++书籍都忠告我们C语言宏是万恶之首，但事情总不如我们想象的那么坏，就如同goto一样。宏有<br>一个很大的作用，就是自动为我们产生代码。如果说模板可以为我们产生各种型别的代码(型别替换)，<br>那么宏其实可以为我们在符号上产生新的代码(即符号替换、增加)。</p>
<p style="FONT-SIZE: 10pt">关于宏的一些语法问题，可以在google上找到。相信我，你对于宏的了解绝对没你想象的那么多。如果你<br>还不知道#和##，也不知道prescan，那么你肯定对宏的了解不够。</p>
<p style="FONT-SIZE: 10pt">我稍微讲解下宏的一些语法问题(说语法问题似乎不妥，macro只与preprocessor有关，跟语义分析又无关)：</p>
<p style="FONT-SIZE: 10pt">1. 宏可以像函数一样被定义，例如：<br>&nbsp;&nbsp; #define min(x,y) (x&lt;y?x:y) //事实上这个宏存在BUG<br>&nbsp;&nbsp; 但是在实际使用时，只有当写上min()，必须加括号，min才会被作为宏展开，否则不做任何处理。<br>&nbsp;&nbsp; <br>2. 如果宏需要参数，你可以不传，编译器会给你警告(宏参数不够)，但是这会导致错误。如C++书籍中所描<br>&nbsp;&nbsp; 述的，编译器(预处理器)对宏的语法检查不够，所以更多的检查性工作得你自己来做。</p>
<p style="FONT-SIZE: 10pt">3. 很多程序员不知道的#和##<br>&nbsp;&nbsp; #符号把一个符号直接转换为字符串，例如：<br>&nbsp;&nbsp; #define STRING(x) #x<br>&nbsp;&nbsp; const char *str = STRING( test_string ); str的内容就是"test_string"，也就是说#会把其后的符号<br>&nbsp;&nbsp; 直接加上双引号。<br>&nbsp;&nbsp; ##符号会连接两个符号，从而产生新的符号(词法层次)，例如：<br>&nbsp;&nbsp; #define SIGN( x ) INT_##x<br>&nbsp;&nbsp; int SIGN( 1 ); 宏被展开后将成为：int INT_1; </p>
<p style="FONT-SIZE: 10pt">4. 变参宏，这个比较酷，它使得你可以定义类似的宏：<br>&nbsp;&nbsp; #define LOG( format, ... ) printf( format, __VA_ARGS__ )<br>&nbsp;&nbsp; LOG( "%s %d", str, count );<br>&nbsp;&nbsp; __VA_ARGS__是系统预定义宏，被自动替换为参数列表。</p>
<p style="FONT-SIZE: 10pt">5. 当一个宏自己调用自己时，会发生什么？例如：<br>&nbsp;&nbsp; #define TEST( x ) ( x + TEST( x ) )<br>&nbsp;&nbsp; TEST( 1 ); 会发生什么？为了防止无限制递归展开，语法规定，当一个宏遇到自己时，就停止展开，也就是<br>&nbsp;&nbsp; 说，当对TEST( 1 )进行展开时，展开过程中又发现了一个TEST，那么就将这个TEST当作一般的符号。TEST(1)<br>&nbsp;&nbsp; 最终被展开为：1 + TEST( 1) 。</p>
<p style="FONT-SIZE: 10pt">6. 宏参数的prescan，<br>&nbsp;&nbsp; 当一个宏参数被放进宏体时，这个宏参数会首先被全部展开(有例外，见下文)。当展开后的宏参数被放进宏体时，<br>&nbsp;&nbsp; 预处理器对新展开的宏体进行第二次扫描，并继续展开。例如：<br>&nbsp;&nbsp; #define PARAM( x ) x<br>&nbsp;&nbsp; #define ADDPARAM( x ) INT_##x<br>&nbsp;&nbsp; PARAM( ADDPARAM( 1 ) ); <br>&nbsp;&nbsp; 因为ADDPARAM( 1 ) 是作为PARAM的宏参数，所以先将ADDPARAM( 1 )展开为INT_1，然后再将INT_1放进PARAM。<br>&nbsp;&nbsp; <br>&nbsp;&nbsp; 例外情况是，如果PARAM宏里对宏参数使用了#或##，那么宏参数不会被展开：<br>&nbsp;&nbsp; #define PARAM( x ) #x<br>&nbsp;&nbsp; #define ADDPARAM( x ) INT_##x<br>&nbsp;&nbsp; PARAM( ADDPARAM( 1 ) ); 将被展开为"ADDPARAM( 1 )"。</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp; 使用这么一个规则，可以创建一个很有趣的技术：打印出一个宏被展开后的样子，这样可以方便你分析代码：<br>&nbsp;&nbsp; #define TO_STRING( x ) TO_STRING1( x )<br>&nbsp;&nbsp; #define TO_STRING1( x ) #x<br>&nbsp;&nbsp; TO_STRING首先会将x全部展开(如果x也是一个宏的话)，然后再传给TO_STRING1转换为字符串，现在你可以这样：<br>&nbsp;&nbsp; const char *str = TO_STRING( PARAM( ADDPARAM( 1 ) ) );去一探PARAM展开后的样子。</p>
<p style="FONT-SIZE: 10pt">7. 一个很重要的补充：就像我在第一点说的那样，如果一个像函数的宏在使用时没有出现括号，那么预处理器只是<br>&nbsp;&nbsp; 将这个宏作为一般的符号处理(那就是不处理)。</p>
<p style="FONT-SIZE: 10pt"><br>我们来见识一下宏是如何帮助我们自动产生代码的。如我所说，宏是在符号层次产生代码。我在分析Boost.Function<br>模块时，因为它使用了大量的宏(宏嵌套，再嵌套)，导致我压根没看明白代码。后来发现了一个小型的模板库ttl，说的<br>是开发一些小型组件去取代部分Boost(这是一个好理由，因为Boost确实太大)。同样，这个库也包含了一个function库。<br>这里的function也就是我之前提到的functor。ttl.function库里为了自动产生很多类似的代码，使用了一个宏：</p>
<p style="FONT-SIZE: 10pt">#define TTL_FUNC_BUILD_FUNCTOR_CALLER(n)&nbsp; \<br>&nbsp;template&lt; typename R, TTL_TPARAMS(n) &gt; \<br>&nbsp;struct functor_caller_base##n \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///...<br>该宏的最终目的是：通过类似于TTL_FUNC_BUILD_FUNCTOR_CALLER(1)的调用方式，自动产生很多functor_caller_base模板：<br>template &lt;typename R, typename T1&gt; struct functor_caller_base1<br>template &lt;typename R, typename T1, typename T2&gt; struct functor_caller_base2<br>template &lt;typename R, typename T1, typename T2, typename T3&gt; struct functor_caller_base3<br>///... <br>那么，核心部分在于TTL_TPARAMS(n)这个宏，可以看出这个宏最终产生的是：<br>typename T1<br>typename T1, typename T2<br>typename T1, typename T2, typename T3<br>///...<br>我们不妨分析TTL_TPARAMS(n)的整个过程。分析宏主要把握我以上提到的一些要点即可。以下过程我建议你翻着ttl的代码，<br>相关代码文件：function.hpp, macro_params.hpp, macro_repeat.hpp, macro_misc.hpp, macro_counter.hpp。</p>
<p style="FONT-SIZE: 10pt">so, here we go </p>
<p style="FONT-SIZE: 10pt">分析过程，逐层分析，逐层展开，例如TTL_TPARAMS(1)：</p>
<p style="FONT-SIZE: 10pt">#define TTL_TPARAMS(n) TTL_TPARAMSX(n,T)&nbsp; <br>=&gt; TTL_TPARAMSX( 1, T )<br>#define TTL_TPARAMSX(n,t) TTL_REPEAT(n, TTL_TPARAM, TTL_TPARAM_END, t)<br>=&gt; TTL_REPEAT( 1, TTL_TPARAM, TTL_TPARAM_END, T )<br>#define TTL_TPARAM(n,t) typename t##n, <br>#define TTL_TPARAM_END(n,t) typename t##n<br>#define TTL_REPEAT(n, m, l, p) TTL_APPEND(TTL_REPEAT_, TTL_DEC(n))(m,l,p) TTL_APPEND(TTL_LAST_REPEAT_,n)(l,p)<br>注意，TTL_TPARAM, TTL_TPARAM_END虽然也是两个宏，他们被作为TTL_REPEAT宏的参数，按照prescan规则，似乎应该先将<br>这两个宏展开再传给TTL_REPEAT。但是，如同我在前面重点提到的，这两个宏是function-like macro，使用时需要加括号，<br>如果没加括号，则不当作宏处理。因此，展开TTL_REPEAT时，应该为：<br>=&gt; TTL_APPEND( TTL_REPEAT_, TTL_DEC(1))(TTL_TPARAM,TTL_TPARAM_END,T) TTL_APPEND( TTL_LAST_REPEAT_,1)(<br>TTL_TPARAM_END,T)<br>这个宏体看起来很复杂，仔细分析下，可以分为两部分：<br>TTL_APPEND( TTL_REPEAT_, TTL_DEC(1))(TTL_TPARAM,TTL_TPARAM_END,T)以及<br>TTL_APPEND( TTL_LAST_REPEAT_,1)(TTL_TPARAM_END,T)<br>先分析第一部分：<br>#define TTL_APPEND( x, y ) TTL_APPEND1(x,y) //先展开x,y再将x,y连接起来<br>#define TTL_APPEND1( x, y ) x ## y<br>#define TTL_DEC(n) TTL_APPEND(TTL_CNTDEC_, n)<br>根据先展开参数的原则，会先展开TTL_DEC(1)<br>=&gt; TTL_APPEND(TTL_CNTDEC_,1) =&gt; TTL_CNTDEC_1 <br>#define TTL_CNTDEC_1 0&nbsp; 注意，TTL_CNTDEC_不是宏，TTL_CNTDEC_1是一个宏。<br>=&gt; 0 ， 也就是说，TTL_DEC(1)最终被展开为0。回到TTL_APPEND部分：<br>=&gt; TTL_REPEAT_0 (TTL_TPARAM,TTL_TPARAM_END,T) <br>#define TTL_REPEAT_0(m,l,p)<br>TTL_REPEAT_0这个宏为空，那么，上面说的第一部分被忽略，现在只剩下第二部分：<br>TTL_APPEND( TTL_LAST_REPEAT_,1)(TTL_TPARAM_END,T)<br>=&gt; TTL_LAST_REPEAT_1 (TTL_TPARAM_END,T) // TTL_APPEND将TTL_LAST_REPEAT_和1合并起来<br>#define TTL_LAST_REPEAT_1(m,p) m(1,p)<br>=&gt; TTL_TPARAM_END( 1, T )<br>#define TTL_TPARAM_END(n,t) typename t##n<br>=&gt; typename T1&nbsp; 展开完毕。</p>
<p style="FONT-SIZE: 10pt">虽然我们分析出来了，但是这其实并不是我们想要的。我们应该从那些宏里去获取作者关于宏的编程思想。很好地使用宏<br>看上去似乎是一些偏门的奇技淫巧，但是他确实可以让我们编码更自动化。</p>
<p style="FONT-SIZE: 10pt">参考资料：<br>macro语法: http://developer.apple.com/documentation/DeveloperTools/gcc-4.0.1/cpp/Macros.html<br>ttl(tiny template library) : <a href="http://tinytl.sourceforge.net/">http://tinytl.sourceforge.net/</a></p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp; <br>&nbsp;</p>
<img src ="http://www.cppblog.com/kevinlynx/aggbug/44828.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2008-03-19 10:34 <a href="http://www.cppblog.com/kevinlynx/archive/2008/03/19/44828.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实现functor - 增强型的函数指针</title><link>http://www.cppblog.com/kevinlynx/archive/2008/03/17/44678.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Mon, 17 Mar 2008 03:13:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2008/03/17/44678.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/44678.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2008/03/17/44678.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/44678.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/44678.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 作者：Kevin Lynx需求：开发一种组件，用以包装C函数、通常的函数对象、成员函数，使其对外保持一种一致的接口。我将最终的组件称为functor，这里的functor与loki中的functor以及boost中的function功能一致，同STL中的functor在概念层次上可以说也是一样的。那么，functor其实也可以进一步传进其他functor构成新的functor。C++世...&nbsp;&nbsp;<a href='http://www.cppblog.com/kevinlynx/archive/2008/03/17/44678.html'>阅读全文</a><img src ="http://www.cppblog.com/kevinlynx/aggbug/44678.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2008-03-17 11:13 <a href="http://www.cppblog.com/kevinlynx/archive/2008/03/17/44678.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>分析stl function objects模块</title><link>http://www.cppblog.com/kevinlynx/archive/2008/03/13/44362.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Thu, 13 Mar 2008 05:31:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2008/03/13/44362.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/44362.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2008/03/13/44362.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/44362.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/44362.html</trackback:ping><description><![CDATA[<p style="FONT-SIZE: 10pt"><br>从SGI的STl文档来看，STL functor(function object)模块主要分为两个部分：预先定义的functor<br>以及functor adaptors。除此之外，为了使客端程序员写出适用于functor adaptor的functor，STL<br>又定义了一系列基本上只包含typedef的空类型(例如unary_function)。用户只需要派生这些类，即<br>可让自己写的functor被functor adaptor使用。以下称类基类型为base functor。</p>
<p style="FONT-SIZE: 10pt">base functor包括: unary_function, binary_function,分别表示只有一个参数的函数和有两个参数<br>的函数。实际上STL里还有一个所谓的generator，代表没有参数的函数。因为STL泛型算法一般最多<br>只会使用两个参数的函数，所以这里并没有定义更多参数的base functor。</p>
<p style="FONT-SIZE: 10pt">可被functor adaptor使用的functor又称为adaptable function，根据参数的个数，会被命名为诸如<br>adaptable unary function, adaptable binary function。</p>
<p style="FONT-SIZE: 10pt">一个返回值为bool的functor又被称为predicate，可被用于functor adaptor的predicate被称为<br>adaptable predicate。其实所谓的adaptable，只需要在类型内部typedef一些类型即可，一般包括<br>first_argument_type, second_argument_type, result_type。functor adaptor会使用这些定义。</p>
<p style="FONT-SIZE: 10pt">预定义的functors都是些很简单的functor，基本上就是封装诸如plus, minus, equal_to之类的算术<br>运算，列举一个predefined functor的代码：<br>&nbsp; </p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">template&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;_Tp</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;plus&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;binary_function</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">_Tp,&nbsp;_Tp,&nbsp;_Tp</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img id=Codehighlighter1_77_189_Open_Image onclick="this.style.display='none'; Codehighlighter1_77_189_Open_Text.style.display='none'; Codehighlighter1_77_189_Closed_Image.style.display='inline'; Codehighlighter1_77_189_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_77_189_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_77_189_Closed_Text.style.display='none'; Codehighlighter1_77_189_Open_Image.style.display='inline'; Codehighlighter1_77_189_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;</span><span id=Codehighlighter1_77_189_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_77_189_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_Tp&nbsp;</span><span style="COLOR: #0000ff">operator</span><span style="COLOR: #000000">()(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;_Tp</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;__x,&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;_Tp</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;__y)&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img id=Codehighlighter1_145_181_Open_Image onclick="this.style.display='none'; Codehighlighter1_145_181_Open_Text.style.display='none'; Codehighlighter1_145_181_Closed_Image.style.display='inline'; Codehighlighter1_145_181_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_145_181_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_145_181_Closed_Text.style.display='none'; Codehighlighter1_145_181_Open_Image.style.display='inline'; Codehighlighter1_145_181_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_145_181_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_145_181_Open_Text><span style="COLOR: #000000">{&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;__x&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;__y;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">;</span></div>
<p style="FONT-SIZE: 10pt"><br>因为从binary_function(即我所谓的base functor)派生，因此这些predefined functor也是adaptable <br>function。</p>
<p style="FONT-SIZE: 10pt">functor adaptors里有很多有趣的东西，其实functor adaptor也是一些functor(从SGI的观点来看，一般<br>的C函数，函数指针都算作functor)。所不同的是，他们通常会适配(adapt)一种functor到另一种。例如：<br>std::binder1st，严格地说它是一个函数模板，它会把一个adaptable binary function转换为一个<br>adaptable unary function，并绑定一个参数。又如: std::ptr_fun，它会将一个只有一个参数的C函数<br>适配成一个pointer_to_unary_function的functor。</p>
<p style="FONT-SIZE: 10pt">下面列举一些具体的代码：<br>关于base functor，基本上就只有unary_function, binary_function :<br>&nbsp; </p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">template&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;_Arg,&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;_Result</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;unary_function<br><img id=Codehighlighter1_63_157_Open_Image onclick="this.style.display='none'; Codehighlighter1_63_157_Open_Text.style.display='none'; Codehighlighter1_63_157_Closed_Image.style.display='inline'; Codehighlighter1_63_157_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_63_157_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_63_157_Closed_Text.style.display='none'; Codehighlighter1_63_157_Open_Image.style.display='inline'; Codehighlighter1_63_157_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;</span><span id=Codehighlighter1_63_157_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_63_157_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;_Arg&nbsp;argument_type;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;_Result&nbsp;result_type;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;</span></div>
<p style="FONT-SIZE: 10pt"><br>关于predefined functor，如之前列举的plus一样，再列举一个：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">template&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;_Tp</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;greater&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;binary_function</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">_Tp,&nbsp;_Tp,&nbsp;</span><span style="COLOR: #0000ff">bool</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img id=Codehighlighter1_79_194_Open_Image onclick="this.style.display='none'; Codehighlighter1_79_194_Open_Text.style.display='none'; Codehighlighter1_79_194_Closed_Image.style.display='inline'; Codehighlighter1_79_194_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_79_194_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_79_194_Closed_Text.style.display='none'; Codehighlighter1_79_194_Open_Image.style.display='inline'; Codehighlighter1_79_194_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;</span><span id=Codehighlighter1_79_194_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_79_194_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">bool</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">operator</span><span style="COLOR: #000000">()(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;_Tp</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;__x,&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;_Tp</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;__y)&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"><br><img id=Codehighlighter1_151_187_Open_Image onclick="this.style.display='none'; Codehighlighter1_151_187_Open_Text.style.display='none'; Codehighlighter1_151_187_Closed_Image.style.display='inline'; Codehighlighter1_151_187_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_151_187_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_151_187_Closed_Text.style.display='none'; Codehighlighter1_151_187_Open_Image.style.display='inline'; Codehighlighter1_151_187_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_151_187_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_151_187_Open_Text><span style="COLOR: #000000">{&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;__x&nbsp;</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;__y;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p style="FONT-SIZE: 10pt">&nbsp;<br>关于functor adaptors，也是我觉得比较有趣的部分，多列举几个：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">template&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;_Operation,&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;_Tp</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;inline&nbsp;binder1st</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">_Operation</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;bind1st(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;_Operation</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;__fn,&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;_Tp</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;__x)<br><img id=Codehighlighter1_122_252_Open_Image onclick="this.style.display='none'; Codehighlighter1_122_252_Open_Text.style.display='none'; Codehighlighter1_122_252_Closed_Image.style.display='inline'; Codehighlighter1_122_252_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_122_252_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_122_252_Closed_Text.style.display='none'; Codehighlighter1_122_252_Open_Image.style.display='inline'; Codehighlighter1_122_252_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;</span><span id=Codehighlighter1_122_252_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_122_252_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;typename&nbsp;_Operation::first_argument_type&nbsp;_Arg1_type;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;binder1st</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">_Operation</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">(__fn,&nbsp;_Arg1_type(__x));<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;</span></div>
<p style="FONT-SIZE: 10pt">&nbsp; <br>bind1st返回的binder1st定义为：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">&nbsp;template&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;_Operation</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;binder1st&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;unary_function</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">typename&nbsp;_Operation::second_argument_type,&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;typename&nbsp;_Operation::result_type</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img id=Codehighlighter1_153_710_Open_Image onclick="this.style.display='none'; Codehighlighter1_153_710_Open_Text.style.display='none'; Codehighlighter1_153_710_Closed_Image.style.display='inline'; Codehighlighter1_153_710_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_153_710_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_153_710_Closed_Text.style.display='none'; Codehighlighter1_153_710_Open_Image.style.display='inline'; Codehighlighter1_153_710_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;</span><span id=Codehighlighter1_153_710_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_153_710_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_Operation&nbsp;op;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;_Operation::first_argument_type&nbsp;value;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;binder1st(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;_Operation</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;__x,&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;typename&nbsp;_Operation::first_argument_type</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;__y):&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;op(__x),&nbsp;value(__y)&nbsp;<br><img id=Codehighlighter1_382_383_Open_Image onclick="this.style.display='none'; Codehighlighter1_382_383_Open_Text.style.display='none'; Codehighlighter1_382_383_Closed_Image.style.display='inline'; Codehighlighter1_382_383_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_382_383_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_382_383_Closed_Text.style.display='none'; Codehighlighter1_382_383_Open_Image.style.display='inline'; Codehighlighter1_382_383_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_382_383_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_382_383_Open_Text><span style="COLOR: #000000">{}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;_Operation::result_type&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">operator</span><span style="COLOR: #000000">()(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;typename&nbsp;_Operation::second_argument_type</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;__x)&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"><br><img id=Codehighlighter1_508_550_Open_Image onclick="this.style.display='none'; Codehighlighter1_508_550_Open_Text.style.display='none'; Codehighlighter1_508_550_Closed_Image.style.display='inline'; Codehighlighter1_508_550_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_508_550_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_508_550_Closed_Text.style.display='none'; Codehighlighter1_508_550_Open_Image.style.display='inline'; Codehighlighter1_508_550_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_508_550_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_508_550_Open_Text><span style="COLOR: #000000">{&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;op(value,&nbsp;__x);&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename&nbsp;_Operation::result_type&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">operator</span><span style="COLOR: #000000">()(typename&nbsp;_Operation::second_argument_type</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;__x)&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"><br><img id=Codehighlighter1_666_706_Open_Image onclick="this.style.display='none'; Codehighlighter1_666_706_Open_Text.style.display='none'; Codehighlighter1_666_706_Closed_Image.style.display='inline'; Codehighlighter1_666_706_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_666_706_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_666_706_Closed_Text.style.display='none'; Codehighlighter1_666_706_Open_Image.style.display='inline'; Codehighlighter1_666_706_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_666_706_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_666_706_Open_Text><span style="COLOR: #000000">{&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;op(value,&nbsp;__x);&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p style="FONT-SIZE: 10pt">&nbsp;<br>值得一提的是，ptr_fun以及相关的pointer_to_unary_function, pointer_to_binary_function，基本上<br>就是用来绑定C函数的组件，不过这里采用了很基础的模板技术，因此只实现了绑定一个参数和两个参数<br>的C函数。这种组件类似于loki中的functor，以及boost中的bind，只是功能弱很多。与之相关的还有<br>mem_fun, mem_fun_ref, mem_fun1, mem_fun1_ref等，这些都是用于绑定成员函数的。另一方面，与其说<br>是绑定，还不如说适配，即将函数适配为functor(特指重载operator()的类)。( Mem_fun_t is an adaptor<br>&nbsp;for member functions )采用这些(ptr_fun, mem_fun之类的东西)组件，客端程序员可以很容易地将各种<br>运行体(Kevin似乎很喜欢发明各种名字)(C函数、成员函数)适配成functor，从而与STL泛型算法结合。<br>例如, SGI文档中给出的mem_fun例子：</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id=Codehighlighter1_9_38_Open_Image onclick="this.style.display='none'; Codehighlighter1_9_38_Open_Text.style.display='none'; Codehighlighter1_9_38_Closed_Image.style.display='inline'; Codehighlighter1_9_38_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_9_38_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_9_38_Closed_Text.style.display='none'; Codehighlighter1_9_38_Open_Image.style.display='inline'; Codehighlighter1_9_38_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;B&nbsp;</span><span id=Codehighlighter1_9_38_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_9_38_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;print()&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_63_111_Open_Image onclick="this.style.display='none'; Codehighlighter1_63_111_Open_Text.style.display='none'; Codehighlighter1_63_111_Closed_Image.style.display='inline'; Codehighlighter1_63_111_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_63_111_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_63_111_Closed_Text.style.display='none'; Codehighlighter1_63_111_Open_Image.style.display='inline'; Codehighlighter1_63_111_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;D1&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;B&nbsp;</span><span id=Codehighlighter1_63_111_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_63_111_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_79_109_Open_Image onclick="this.style.display='none'; Codehighlighter1_79_109_Open_Text.style.display='none'; Codehighlighter1_79_109_Closed_Image.style.display='inline'; Codehighlighter1_79_109_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_79_109_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_79_109_Closed_Text.style.display='none'; Codehighlighter1_79_109_Open_Image.style.display='inline'; Codehighlighter1_79_109_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;print()&nbsp;</span><span id=Codehighlighter1_79_109_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_79_109_Open_Text><span style="COLOR: #000000">{&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">I'm&nbsp;a&nbsp;D1</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_136_184_Open_Image onclick="this.style.display='none'; Codehighlighter1_136_184_Open_Text.style.display='none'; Codehighlighter1_136_184_Closed_Image.style.display='inline'; Codehighlighter1_136_184_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_136_184_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_136_184_Closed_Text.style.display='none'; Codehighlighter1_136_184_Open_Image.style.display='inline'; Codehighlighter1_136_184_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;D2&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;B&nbsp;</span><span id=Codehighlighter1_136_184_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_136_184_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_152_182_Open_Image onclick="this.style.display='none'; Codehighlighter1_152_182_Open_Text.style.display='none'; Codehighlighter1_152_182_Closed_Image.style.display='inline'; Codehighlighter1_152_182_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_152_182_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_152_182_Closed_Text.style.display='none'; Codehighlighter1_152_182_Open_Image.style.display='inline'; Codehighlighter1_152_182_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;print()&nbsp;</span><span id=Codehighlighter1_152_182_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_152_182_Open_Text><span style="COLOR: #000000">{&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">I'm&nbsp;a&nbsp;D2</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br><img id=Codehighlighter1_199_357_Open_Image onclick="this.style.display='none'; Codehighlighter1_199_357_Open_Text.style.display='none'; Codehighlighter1_199_357_Closed_Image.style.display='inline'; Codehighlighter1_199_357_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_199_357_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_199_357_Closed_Text.style.display='none'; Codehighlighter1_199_357_Open_Image.style.display='inline'; Codehighlighter1_199_357_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_199_357_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_199_357_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;vector</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">B</span><span style="COLOR: #000000">*&gt;</span><span style="COLOR: #000000">&nbsp;V;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;V.push_back(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;D1);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;V.push_back(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;D2);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;V.push_back(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;D2);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;V.push_back(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;D1);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;for_each(V.begin(),&nbsp;V.end(),&nbsp;mem_fun(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">B::print));<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">注：以上分析基于dev-cpp中自带的stl，源代码见stl_functional.h。</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<img src ="http://www.cppblog.com/kevinlynx/aggbug/44362.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2008-03-13 13:31 <a href="http://www.cppblog.com/kevinlynx/archive/2008/03/13/44362.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>最近接触的东西</title><link>http://www.cppblog.com/kevinlynx/archive/2008/03/13/44322.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Wed, 12 Mar 2008 16:17:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2008/03/13/44322.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/44322.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2008/03/13/44322.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/44322.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/44322.html</trackback:ping><description><![CDATA[<p style="FONT-SIZE: 10pt">平时工作，很好有时间拿来自己安排学习，所以接触的东西比较杂乱。偶尔做个列表，列出最近完成的以及计划安排。<br><br>网络编程，摆弄各种API，其实弄明白了写点实验代码觉得什么都不是。当初想买TCP那三本龙书，想对底层探个究竟，可是终究还没能抽出时间。<br><br>网络库，网络库不是把socket不是把IOCP封装起来就可以的。再经历过各种架构，写过一些库代码后，自己对开发库的要求是越来越高。琢磨了良久，我心目中的网络库，即使是用来讨好自己的迷你型的，起码也该进行软件分层，从发送接收层到加解密层到数据校验层到消息层，这么多层次，要做好不容易。心里面其实有想法，无论如何，我应该秉持当初开发edge2d的态度，在真正动手之前先取万家之长。<br><br>MMO服务器分布式架构，不了解之前觉得宏大不可及，接触后其实也觉得没什么。凡事不要害怕，想想看，再深奥的东西，也是人想出来的。一个东西之所以复杂，是因为它经历了长久的变化。如果让我来想，如何通过服务器的分布式架构减轻单个服务器的负载，那我想出来的，最多是几年前的老东西。无论如何，分布式架构的模式在那里。关键是让自己去学着改善学着思考出自己的方案。本来安排了几个网络游戏代码让自己去读。可是竟然如此郁闷地找不到时间。<br><br>模板编程，想来做技术都秉持一个观点，一步一步来，不求多只求精。自己学C++分了好几个阶段，理论，实践，理论，实践。这样磨蹭着过来，一年时间竟也写了10万行代码。之前有过深入接触C++模板编程的想法，看了一阵子书，觉得基本上没获得一种模板实践编程的思想，果然是可学不可用的东西么？后来听说dophi说他们公司有个人被封为&#8216;模板达人&#8217;，自己觉得有点意思。于是08年又把模板拿出来。看了&lt;STL源码剖析&gt;，翻了下STL源码，确实有时候觉得精妙不可言，大有拍案叫绝的感觉。不过从本质上来说，也不过如此。最近又开始看&lt;C++设计新思维&gt;，之前看过英文电子版第一章，对于满世界的policy混沌不已。现在看纸质的书，觉得感觉还行，没有原先想像的那么神圣不可及。现在很高兴有了模板编程的思想，时髦点说是泛型思维。当初很善于玩弄面向对象架构，老喜欢给别人炫耀一个系统的架构（例如我的edge2d)，谈论各种设计模式。现在对于模板，也喜欢满世界地塞template，仿佛全世界都可以泛化一样。凡事有个度，不过自己允许自己在初期过于泛化吧。<br><br>自己模仿着loki写了个functor，觉得很美妙。打算将operator ==和copy constructor整理下就可以用于实践。<br><br>看了下stl的binary_function, unary_function, bind1st, bing2nd之类的functor, functor adapter，觉得真是粗糙不堪。不过我想，这种粗糙也情有可原，毕竟像loki这种挑战编译器极限的玩意，也只能算作程序员的炫耀品了吧？<br><br>准备看boost的bind，现在学技术老爱一杆子全部打下。学了网络编程就想多看几个网络库，自己写了线程池就想看看别人写的线程池，学了模板就四处找template看。so how about boost::bind ?<br><br>瞎摆弄了下asio，实在很想找个东西用来实践下，不想leader不允许。这世界，可学不可用的东西太多太多。<br><br>准备接触linux下的epoll，幻想着它也许就是一个轮询的查询方式，似乎还没IOCP来得优美。也许真正开始linux编程的时候，我也就真正不会使用exception。但是起码现在的观点是，鄙视那些因为C++的高级特性（多态异常所有你能想到的）而带来的C++的所谓低效率的人。如果你认为那么一点点语言机制会拖慢你系统的运行速度，那么你为什么不去看看你那些蜗牛一样的算法？如果你在用C++，那么专业点，努力不要写C风格的class（很别扭，是吧），努力进入C++的世界。我不是C++牛人，因此我不能告诉你C++标准库，C++准标准库，C++那么多那么多优秀的库，为什么要那样做，为什么要使用多态将整个系统抽象起来，为什么要用异常将整个系统throw起来，为什么那么多稀奇古怪的template typename。我只知道，我在写C++程序，所以我跟随这些库的作者。<br><br>内存池，不单单是内存池吧?总之关于自己管理内存的东西，STL里面有allocator(限于SGI的STL），loki里有SmallObject，这些都是不错的东西。如果可以，我会去实现一个allocator，内存分配器。但是如果折中，我会剥离STL的allocator，记住，policy设计方法学告诉我们，组装这些组件！<br><br>线程池，其实原理就那么简单。分配一堆取着用先，不够了再分配，积极回收吧。但是出于对自己多线程编程经验的不自信，我最终不敢炫耀我自己实现的线程池。我想，先培养我和多线程的感情先吧。<br><br>凌乱杂散了这么多，接下来换换重心，集中攻克一方面吧。<br><br></p>
<img src ="http://www.cppblog.com/kevinlynx/aggbug/44322.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2008-03-13 00:17 <a href="http://www.cppblog.com/kevinlynx/archive/2008/03/13/44322.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>