﻿<?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/flyinghare/category/11475.html</link><description>兔子</description><language>zh-cn</language><lastBuildDate>Sat, 08 Sep 2012 08:10:18 GMT</lastBuildDate><pubDate>Sat, 08 Sep 2012 08:10:18 GMT</pubDate><ttl>60</ttl><item><title>汇编获取CPU机器周期个数</title><link>http://www.cppblog.com/flyinghare/archive/2012/09/07/189851.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Fri, 07 Sep 2012 11:17:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2012/09/07/189851.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/189851.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2012/09/07/189851.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/189851.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/189851.html</trackback:ping><description><![CDATA[<p style="color: #333333; text-align: left; background-color: #ffffff; font-size: 13px; line-height: 19px; margin-top: 10px; margin-bottom: 10px; text-indent: 20px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; ">在Pentium以上的CPU中，提供了一条机器指令RDTSC（Read Time Stamp Counter）来读取这个时间戳的数字，并将其保存在EDX:EAX寄存器对中。由于EDX:EAX寄存器对恰好是Win32平台下C++语言保存函数返回值的寄存器，所以我们可以把这条指令看成是一个普通的函数调用。vc2003像这样：<br />inline unsigned __int64 GetTimeStampCount()<br />{<br />__asm RDTSC<br />}<br />对于vc6或者其他编译器可能不行，因为RDTSC不被C++的内嵌汇编器直接支持，所以我们要用_emit伪指令直接嵌入该指令的机器码形式0X0F、0X31，如下：<br />inline unsigned __int64 GetTimeStampCount()<br />{<br />__asm _emit 0x0F<br />__asm _emit 0x31<br />}</p><p style="color: #333333; text-align: left; background-color: #ffffff; font-size: 13px; line-height: 19px; margin-top: 10px; margin-bottom: 10px; text-indent: 20px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; ">&nbsp;</p><p style="color: #333333; text-align: left; background-color: #ffffff; font-size: 13px; line-height: 19px; margin-top: 10px; margin-bottom: 10px; text-indent: 20px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; ">&nbsp;</p><p style="color: #333333; text-align: left; background-color: #ffffff; font-size: 13px; line-height: 19px; margin-top: 10px; margin-bottom: 10px; text-indent: 20px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; ">对关注性能的程序开发人员而言，一个好的计时部件既是益友，也是良师。计时器既可以作为程序组件帮助程序员精确的控制程序进程，又是一件有力的调试武器，在有经验的程序员手里可以尽快的确定程序的性能瓶颈，或者对不同的算法作出有说服力的性能比较。&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; 　　在Windows平台下，常用的计时器有两种，一种是timeGetTime多媒体计时器，它可以提供毫秒级的计时。但这个精度对很多应用场合而言还是太粗糙了。另一种是QueryPerformanceCount计数器，随系统的不同可以提供微秒级的计数。对于实时图形处理、多媒体数据流处理、或者实时系统构造的程序员，善用QueryPerformanceCount/QueryPerformanceFrequency是一项基本功。&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; 　　本文要介绍的，是另一种直接利用Pentium&nbsp;&nbsp; CPU内部时间戳进行计时的高精度计时手段。以下讨论主要得益于《Windows图形编程》一书，第&nbsp;&nbsp; 15页－17页，有兴趣的读者可以直接参考该书。关于RDTSC指令的详细讨论，可以参考Intel产品手册。本文仅仅作抛砖之用。&nbsp;&nbsp;&nbsp;<br />&nbsp; 　　在&nbsp;&nbsp; Intel&nbsp;&nbsp; Pentium以上级别的CPU中，有一个称为&#8220;时间戳（Time&nbsp;&nbsp; Stamp）&#8221;的部件，它以64位无符号整型数的格式，记录了自CPU上电以来所经过的时钟周期数。由于目前的CPU主频都非常高，因此这个部件可以达到纳秒级的计时精度。这个精确性是上述两种方法所无法比拟的。&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; 　　在Pentium以上的CPU中，提供了一条机器指令RDTSC（Read&nbsp;&nbsp; Time&nbsp;&nbsp; Stamp&nbsp;&nbsp; Counter）来读取这个时间戳的数字，并将其保存在EDX:EAX寄存器对中。由于EDX:EAX寄存器对恰好是Win32平台下C++语言保存函数返回值的寄存器，所以我们可以把这条指令看成是一个普通的函数调用。像这样：&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; inline&nbsp;&nbsp; unsigned&nbsp;&nbsp; __int64&nbsp;&nbsp; GetCycleCount()&nbsp;&nbsp;&nbsp;<br />&nbsp; {&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; __asm&nbsp;&nbsp; RDTSC&nbsp;&nbsp;&nbsp;<br />&nbsp; }&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; 但是不行，因为RDTSC不被C++的内嵌汇编器直接支持，所以我们要用_emit伪指令直接嵌入该指令的机器码形式0X0F、0X31，如下：&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; inline&nbsp;&nbsp; unsigned&nbsp;&nbsp; __int64&nbsp;&nbsp; GetCycleCount()&nbsp;&nbsp;&nbsp;<br />&nbsp; {&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; __asm&nbsp;&nbsp; _emit&nbsp;&nbsp; 0x0F&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; __asm&nbsp;&nbsp; _emit&nbsp;&nbsp; 0x31&nbsp;&nbsp;&nbsp;<br />&nbsp; }&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; 以后在需要计数器的场合，可以像使用普通的Win32&nbsp;&nbsp; API一样，调用两次GetCycleCount函数，比较两个返回值的差，像这样：&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; unsigned&nbsp;&nbsp; long&nbsp;&nbsp; t;&nbsp;&nbsp;&nbsp;<br />&nbsp; t&nbsp;&nbsp; =&nbsp;&nbsp; (unsigned&nbsp;&nbsp; long)GetCycleCount();&nbsp;&nbsp;&nbsp;<br />&nbsp; //Do&nbsp;&nbsp; Something&nbsp;&nbsp; time-intensive&nbsp;&nbsp; ...&nbsp;&nbsp;&nbsp;<br />&nbsp; t&nbsp;&nbsp; -=&nbsp;&nbsp; (unsigned&nbsp;&nbsp; long)GetCycleCount();&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; 　　《Windows图形编程》第15页编写了一个类，把这个计数器封装起来。有兴趣的读者可以去参考那个类的代码。作者为了更精确的定时，做了一点小小的改进，把执行RDTSC指令的时间，通过连续两次调用GetCycleCount函数计算出来并保存了起来，以后每次计时结束后，都从实际得到的计数中减掉这一小段时间，以得到更准确的计时数字。但我个人觉得这一点点改进意义不大。在我的机器上实测，这条指令大概花掉了几十到100多个周期，在&nbsp;&nbsp; Celeron&nbsp;&nbsp; 800MHz的机器上，这不过是十分之一微秒的时间。对大多数应用来说，这点时间完全可以忽略不计；而对那些确实要精确到纳秒数量级的应用来说，这个补偿也过于粗糙了。&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; 这个方法的优点是：&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; 1.高精度。可以直接达到纳秒级的计时精度（在1GHz的CPU上每个时钟周期就是一纳秒），这是其他计时方法所难以企及的。&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; 2.&nbsp;&nbsp; 成本低。timeGetTime&nbsp;&nbsp; 函数需要链接多媒体库winmm.lib，QueryPerformance*&nbsp;&nbsp; 函数根据MSDN的说明，需要硬件的支持（虽然我还没有见过不支持的机器）和KERNEL库的支持，所以二者都只能在Windows平台下使用（关于DOS平台下的高精度计时问题，可以参考《图形程序开发人员指南》，里面有关于控制定时器8253的详细说明）。但RDTSC指令是一条CPU指令，凡是i386平台下Pentium以上的机器均支持，甚至没有平台的限制（我相信i386版本UNIX和Linux下这个方法同样适用，但没有条件试验），而且函数调用的开销是最小的。&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; 3.&nbsp;&nbsp; 具有和CPU主频直接对应的速率关系。一个计数相当于1/(CPU主频Hz数)秒，这样只要知道了CPU的主频，可以直接计算出时间。这和&nbsp;&nbsp; QueryPerformanceCount不同，后者需要通过QueryPerformanceFrequency获取当前计数器每秒的计数次数才能换算成时间。&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; 这个方法的缺点是：&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; 1.现有的C/C++编译器多数不直接支持使用RDTSC指令，需要用直接嵌入机器码的方式编程，比较麻烦。&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; 2.数据抖动比较厉害。其实对任何计量手段而言，精度和稳定性永远是一对矛盾。如果用低精度的timeGetTime来计时，基本上每次计时的结果都是相同的；而RDTSC指令每次结果都不一样，经常有几百甚至上千的差距。这是这种方法高精度本身固有的矛盾。&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; 关于这个方法计时的最大长度，我们可以简单的用下列公式计算：&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; 自CPU上电以来的秒数&nbsp;&nbsp; =&nbsp;&nbsp; RDTSC读出的周期数&nbsp;&nbsp; /&nbsp;&nbsp; CPU主频速率（Hz）&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; 64位无符号整数所能表达的最大数字是1.8&#215;10^19，在我的Celeron&nbsp;&nbsp; 800上可以计时大约700年（书中说可以在200MHz的Pentium上计时117年，这个数字不知道是怎么得出来的，与我的计算有出入）。无论如何，我们大可不必关心溢出的问题。&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; 下面是几个小例子，简要比较了三种计时方法的用法与精度&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; //Timer1.cpp&nbsp;&nbsp; 使用了RDTSC指令的Timer类//KTimer类的定义可以参见《Windows图形编程》P15&nbsp;&nbsp;&nbsp;<br />&nbsp; //编译行：CL&nbsp;&nbsp; Timer1.cpp&nbsp;&nbsp; /link&nbsp;&nbsp; USER32.lib&nbsp;&nbsp;&nbsp;<br />&nbsp; #include&nbsp;&nbsp; &amp;ltstdio.h&gt;&nbsp;&nbsp;&nbsp;<br />&nbsp; #include&nbsp;&nbsp; "KTimer.h"&nbsp;&nbsp;&nbsp;<br />&nbsp; main()&nbsp;&nbsp;&nbsp;<br />&nbsp; {&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; unsigned&nbsp;&nbsp; t;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; KTimer&nbsp;&nbsp; timer;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; timer.Start();&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; Sleep(1000);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; t&nbsp;&nbsp; =&nbsp;&nbsp; timer.Stop();&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; printf("Lasting&nbsp;&nbsp; Time:&nbsp;&nbsp; %d\n",t);&nbsp;&nbsp;&nbsp;<br />&nbsp; }&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; //Timer2.cpp&nbsp;&nbsp; 使用了timeGetTime函数&nbsp;&nbsp;&nbsp;<br />&nbsp; //需包含&amp;ltmmsys.h&gt;，但由于Windows头文件错综复杂的关系&nbsp;&nbsp;&nbsp;<br />&nbsp; //简单包含&amp;ltwindows.h&gt;比较偷懒：）&nbsp;&nbsp;&nbsp;<br />&nbsp; //编译行：CL&nbsp;&nbsp; timer2.cpp&nbsp;&nbsp; /link&nbsp;&nbsp; winmm.lib&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; #include&nbsp;&nbsp; &amp;ltwindows.h&gt;&nbsp;&nbsp;&nbsp;<br />&nbsp; #include&nbsp;&nbsp; &amp;ltstdio.h&gt;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; main()&nbsp;&nbsp;&nbsp;<br />&nbsp; {&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; DWORD&nbsp;&nbsp; t1,&nbsp;&nbsp; t2;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; t1&nbsp;&nbsp; =&nbsp;&nbsp; timeGetTime();&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; Sleep(1000);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; t2&nbsp;&nbsp; =&nbsp;&nbsp; timeGetTime();&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; printf("Begin&nbsp;&nbsp; Time:&nbsp;&nbsp; %u\n",&nbsp;&nbsp; t1);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; printf("End&nbsp;&nbsp; Time:&nbsp;&nbsp; %u\n",&nbsp;&nbsp; t2);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; printf("Lasting&nbsp;&nbsp; Time:&nbsp;&nbsp; %u\n",(t2-t1));&nbsp;&nbsp;&nbsp;<br />&nbsp; }&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; //Timer3.cpp&nbsp;&nbsp; 使用了QueryPerformanceCounter函数&nbsp;&nbsp;&nbsp;<br />&nbsp; //编译行：CL&nbsp;&nbsp; timer3.cpp&nbsp;&nbsp; /link&nbsp;&nbsp; KERNEl32.lib&nbsp;&nbsp;&nbsp;<br />&nbsp; #include&nbsp;&nbsp; &amp;ltwindows.h&gt;&nbsp;&nbsp;&nbsp;<br />&nbsp; #include&nbsp;&nbsp; &amp;ltstdio.h&gt;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; main()&nbsp;&nbsp;&nbsp;<br />&nbsp; {&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; LARGE_INTEGER&nbsp;&nbsp; t1,&nbsp;&nbsp; t2,&nbsp;&nbsp; tc;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; QueryPerformanceFrequency(&amp;tc);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; printf("Frequency:&nbsp;&nbsp; %u\n",&nbsp;&nbsp; tc.QuadPart);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; QueryPerformanceCounter(&amp;t1);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; Sleep(1000);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; QueryPerformanceCounter(&amp;t2);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; printf("Begin&nbsp;&nbsp; Time:&nbsp;&nbsp; %u\n",&nbsp;&nbsp; t1.QuadPart);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; printf("End&nbsp;&nbsp; Time:&nbsp;&nbsp; %u\n",&nbsp;&nbsp; t2.QuadPart);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; printf("Lasting&nbsp;&nbsp; Time:&nbsp;&nbsp; %u\n",(&nbsp;&nbsp; t2.QuadPart-&nbsp;&nbsp; t1.QuadPart));&nbsp;&nbsp;&nbsp;<br />&nbsp; }&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; ////////////////////////////////////////////////&nbsp;&nbsp;&nbsp;<br />&nbsp; //以上三个示例程序都是测试1秒钟休眠所耗费的时间&nbsp;&nbsp;&nbsp;<br />&nbsp; file://测/试环境：Celeron&nbsp;&nbsp; 800MHz&nbsp;&nbsp; /&nbsp;&nbsp; 256M&nbsp;&nbsp; SDRAM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Windows&nbsp;&nbsp; 2000&nbsp;&nbsp; Professional&nbsp;&nbsp; SP2&nbsp;&nbsp;&nbsp;<br />&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Microsoft&nbsp;&nbsp; Visual&nbsp;&nbsp; C++&nbsp;&nbsp; 6.0&nbsp;&nbsp; SP5&nbsp;&nbsp;&nbsp;<br />&nbsp; ////////////////////////////////////////////////&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; 以下是Timer1的运行结果，使用的是高精度的RDTSC指令&nbsp;&nbsp;&nbsp;<br />&nbsp; Lasting&nbsp;&nbsp; Time:&nbsp;&nbsp; 804586872&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; 以下是Timer2的运行结果，使用的是最粗糙的timeGetTime&nbsp;&nbsp; API&nbsp;&nbsp;&nbsp;<br />&nbsp; Begin&nbsp;&nbsp; Time:&nbsp;&nbsp; 20254254&nbsp;&nbsp;&nbsp;<br />&nbsp; End&nbsp;&nbsp; Time:&nbsp;&nbsp; 20255255&nbsp;&nbsp;&nbsp;<br />&nbsp; Lasting&nbsp;&nbsp; Time:&nbsp;&nbsp; 1001&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp; 以下是Timer3的运行结果，使用的是QueryPerformanceCount&nbsp;&nbsp; API&nbsp;&nbsp;&nbsp;<br />&nbsp; Frequency:&nbsp;&nbsp; 3579545&nbsp;&nbsp;&nbsp;<br />&nbsp; Begin&nbsp;&nbsp; Time:&nbsp;&nbsp; 3804729124&nbsp;&nbsp;&nbsp;<br />&nbsp; End&nbsp;&nbsp; Time:&nbsp;&nbsp; 3808298836&nbsp;&nbsp;&nbsp;<br />&nbsp; Lasting&nbsp;&nbsp; Time:&nbsp;&nbsp; 3569712 &nbsp;<br /><br />转自：<a href="http://blog.csdn.net/bbs598598/article/details/7441687">http://blog.csdn.net/bbs598598/article/details/7441687</a></p><img src ="http://www.cppblog.com/flyinghare/aggbug/189851.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2012-09-07 19:17 <a href="http://www.cppblog.com/flyinghare/archive/2012/09/07/189851.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>慎用USES_CONVERSION</title><link>http://www.cppblog.com/flyinghare/archive/2012/08/13/187054.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Mon, 13 Aug 2012 04:23:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2012/08/13/187054.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/187054.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2012/08/13/187054.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/187054.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/187054.html</trackback:ping><description><![CDATA[<p style="line-height: normal; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; "><span style="line-height: 20px; font-family: Georgia; color: #666666; font-size: 12px; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; "><span style="-webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; "><strong><a href="http://blog.csdn.net/vcleaner/archive/2007/08/08/1731171.aspx" target="_blank" style="color: #1a8bc8; text-decoration: none; ">慎用USES_CONVERSION</a></strong></span></span></p><p style="line-height: normal; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">USES_CONVERSION是ATL中的一个宏定义。用于编码转换(用的比较多的是CString向LPCWSTR转换)。在ATL下使用要包含头文件#include "atlconv.h"</p><p style="line-height: normal; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">使用USES_CONVERSION一定要小心，它们从堆栈上分配内存，直到调用它的函数返回，该内存不会被释放。如果在一个循环中，这个宏被反复调用几万次，将不可避免的产生stackoverflow。</p><p style="line-height: normal; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">&nbsp;</p><p style="line-height: 19px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">在一个函数的循环体中使用A2W等字符转换宏可能引起栈溢出。</p><p style="line-height: 19px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; "><div style="background-color: #eeeeee; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; border-image: initial; 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 />--><span style="color: #000000; ">#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">atlconv.h</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;fn()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">(</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;USES_CONVERSION;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DoSomething(A2W(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">SomeString</span><span style="color: #000000; ">"</span><span style="color: #000000; ">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</span></div></p><p style="line-height: 19px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">让我们来分析以上的转换宏</p><p style="line-height: 19px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; "><div style="background-color: #eeeeee; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; border-image: initial; 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 />--><span style="color: #0000FF; ">#define</span><span style="color: #000000; ">&nbsp;A2W(lpa)&nbsp;(\</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;((_lpa&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;lpa)&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;NULL)&nbsp;</span><span style="color: #000000; ">?</span><span style="color: #000000; ">&nbsp;NULL&nbsp;:&nbsp;(\<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_convert&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(lstrlenA(_lpa)</span><span style="color: #000000; ">+</span><span style="color: #000000; ">1</span><span style="color: #000000; ">),\<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ATLA2WHELPER((LPWSTR)&nbsp;alloca(_convert</span><span style="color: #000000; ">*</span><span style="color: #000000; ">2</span><span style="color: #000000; ">),&nbsp;_lpa,&nbsp;_convert)))<br /></span><span style="color: #0000FF; ">#define</span><span style="color: #000000; ">&nbsp;ATLA2WHELPER&nbsp;AtlA2WHelper</span><span style="color: #000000; "><br />inline&nbsp;LPWSTR&nbsp;WINAPI&nbsp;AtlA2WHelper(LPWSTR&nbsp;lpw,&nbsp;LPCSTR&nbsp;lpa,&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;nChars,&nbsp;UINT&nbsp;acp)<br />{<br />&nbsp;&nbsp;&nbsp;ATLASSERT(lpa&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;NULL);<br />&nbsp;&nbsp;&nbsp;ATLASSERT(lpw&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;NULL);<br />&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;verify&nbsp;that&nbsp;no&nbsp;illegal&nbsp;character&nbsp;present<br />&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;since&nbsp;lpw&nbsp;was&nbsp;allocated&nbsp;based&nbsp;on&nbsp;the&nbsp;size&nbsp;of&nbsp;lpa<br />&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;don't&nbsp;worry&nbsp;about&nbsp;the&nbsp;number&nbsp;of&nbsp;chars</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;lpw[</span><span style="color: #000000; ">0</span><span style="color: #000000; ">]&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">'</span><span style="color: #000000; ">\0</span><span style="color: #000000; ">'</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;MultiByteToWideChar(acp,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;lpa,&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;lpw,&nbsp;nChars);<br />&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;lpw;<br />}</span></div></p><p style="line-height: 19px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">关键的地方在 alloca&nbsp; 内存分配内存上。<br /><div style="background-color: #eeeeee; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; border-image: initial; 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 />--><span style="color: #0000FF; ">#define</span><span style="color: #000000; ">&nbsp;alloca&nbsp;&nbsp;_alloca</span></div></p><p style="line-height: 19px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">_alloca<br />Allocates memory on the stack.</p><p style="line-height: 19px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">Remarks<br />_alloca allocates size bytes from the program stack. The allocated space is automatically freed when the calling function</p><p style="line-height: 19px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">exits. Therefore, do not pass the pointer value returned by _alloca as an argument to free.</p><p style="line-height: 19px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">问题就在这里，分配的内存是在函数的栈中分配的。而VC编译器默认的栈内存空间是2M。当在一个函数中循环调用它时就会不断的分配栈中的内存。</p><p style="line-height: 19px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">以上问题的解决办法：<br />1、自己写字符转换函数，不要偷懒<br /><div style="background-color: #eeeeee; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; border-image: initial; 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 />--><span style="color: #000000; ">Function&nbsp;that&nbsp;safely&nbsp;converts&nbsp;a&nbsp;</span><span style="color: #000000; ">'</span><span style="color: #000000; ">WCHAR</span><span style="color: #000000; ">'</span><span style="color: #000000; ">&nbsp;String&nbsp;to&nbsp;</span><span style="color: #000000; ">'</span><span style="color: #000000; ">LPSTR</span><span style="color: #000000; ">'</span><span style="color: #000000; ">:<br /></span><span style="color: #0000FF; ">char</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;ConvertLPWSTRToLPSTR&nbsp;(LPWSTR&nbsp;lpwszStrIn)<br />{<br />&nbsp;&nbsp;LPSTR&nbsp;pszOut&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;NULL;<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(lpwszStrIn&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;NULL)<br />&nbsp;&nbsp;{<br />&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;nInputStrLen&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;wcslen&nbsp;(lpwszStrIn);<br />&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Double&nbsp;NULL&nbsp;Termination</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;nOutputStrLen&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;WideCharToMultiByte&nbsp;(CP_ACP,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;lpwszStrIn,&nbsp;nInputStrLen,&nbsp;NULL,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">2</span><span style="color: #000000; ">;<br />&nbsp;pszOut&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">char</span><span style="color: #000000; ">&nbsp;[nOutputStrLen];<br />&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(pszOut)<br />&nbsp;{<br />&nbsp;&nbsp;&nbsp;memset&nbsp;(pszOut,&nbsp;</span><span style="color: #000000; ">0x00</span><span style="color: #000000; ">,&nbsp;nOutputStrLen);<br />&nbsp;&nbsp;&nbsp;WideCharToMultiByte(CP_ACP,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;lpwszStrIn,&nbsp;nInputStrLen,&nbsp;pszOut,&nbsp;nOutputStrLen,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">);<br />&nbsp;}<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;pszOut;<br />}</span></div></p><p style="line-height: 19px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">等等一个一个的实现。</p><p style="line-height: 19px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">2、把字符转换部分放到一个函数中处理。</p><p style="line-height: 19px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; "><div style="background-color: #eeeeee; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; border-image: initial; 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 />--><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;fn2()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;USES_CONVERSION;<br />&nbsp;&nbsp;&nbsp;&nbsp;DoSomething(A2W(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">SomeString</span><span style="color: #000000; ">"</span><span style="color: #000000; ">));<br />}<br /></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;fn()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">(</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fn2();<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</span></div></p><p style="line-height: 19px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">如果不知道这点问题，在使用后崩溃时很难查出崩溃原因的。</p><br />转自：<a href="http://www.cnblogs.com/carekee/articles/1935789.html">http://www.cnblogs.com/carekee/articles/1935789.html</a>&nbsp;<br /><br /><img src ="http://www.cppblog.com/flyinghare/aggbug/187054.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2012-08-13 12:23 <a href="http://www.cppblog.com/flyinghare/archive/2012/08/13/187054.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++new失败的处理</title><link>http://www.cppblog.com/flyinghare/archive/2012/06/14/178812.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Thu, 14 Jun 2012 08:27:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2012/06/14/178812.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/178812.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2012/06/14/178812.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/178812.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/178812.html</trackback:ping><description><![CDATA[<div style="font-family: Tahoma; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; font-size: 12px; line-height: 30px; margin-top: -5px; margin-right: 0px; margin-bottom: 0px; margin-left: 1px; color: #555555; text-align: -webkit-left; background-color: #ffffff; ">2009-09-19 16:42</div><table style="font-family: Tahoma, sans-serif; table-layout: fixed; background-color: #ffffff; width: 896px; "><tbody><tr><td style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; font-size: 12px; line-height: 18px; "><div id="blog_text" style="font-family: Consolas; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; font-size: 14px; padding-right: 222px; color: #555555; overflow-x: hidden; overflow-y: hidden; position: relative !important; border-image: initial; ">我们都知道，使用 malloc/calloc 等分配内存的函数时，一定要检查其返回值是否为&#8220;空指针&#8221;（亦即检查分配内存的操作是否成功），这是良好的编程习惯，也是编写可靠程序所必需的。但是，如果你简单地把这一招应用到 new 上，那可就不一定正确了。我经常看到类似这样的代码：<p style="font-family: Tahoma, sans-serif; line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int* p = new int[SIZE];<br style="line-height: normal; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( p == 0 ) // 检查 p 是否空指针<br style="line-height: normal; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br style="line-height: normal; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 其它代码</p><p style="font-family: Tahoma, sans-serif; line-height: 22px; ">&nbsp;&nbsp;&nbsp; 其实，这里的 if ( p == 0 ) 完全是没啥意义的。C++ 里，如果 new 分配内存失败，默认是<strong style="line-height: normal; ">抛出异常</strong>的。所以，如果分配成功，p == 0 就绝对不会成立；而如果分配失败了，也不会执行 if ( p == 0 )，因为分配失败时，new 就会<strong style="line-height: normal; ">抛出异常跳过后面的代码</strong>。如果你想检查 new 是否成功，应该<strong style="line-height: normal; ">捕捉异常</strong>：</p><p style="font-family: Tahoma, sans-serif; line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br style="line-height: normal; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int* p = new int[SIZE];<br style="line-height: normal; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 其它代码<br style="line-height: normal; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch ( const bad_alloc&amp; e ) {<br style="line-height: normal; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br style="line-height: normal; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><p style="font-family: Tahoma, sans-serif; line-height: 22px; ">&nbsp;&nbsp;&nbsp; 据说一些老的编译器里，new 如果分配内存失败，是不抛出异常的（大概是因为那时 C++ 还没加入异常机制），而是和 malloc 一样，返回空指针。不过我从来都没遇到过 new 返回空指针的情况。</p><p style="font-family: Tahoma, sans-serif; line-height: 22px; ">&nbsp;&nbsp;&nbsp; 当然，标准 C++ 亦提供了一个方法来<strong style="line-height: normal; ">抑制 new 抛出异常</strong>，而返回空指针：</p><p style="font-family: Tahoma, sans-serif; line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int* p = new (std::nothrow) int; // 这样如果 new 失败了，就不会抛出异常，而是返回空指针<br style="line-height: normal; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( p == 0 ) // 如此这般，这个判断就有意义了<br style="line-height: normal; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br style="line-height: normal; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 其它代码</p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; "><span style="line-height: normal; ">===============================</span><span style="line-height: normal; ">详解</span><span style="line-height: normal; ">===================================</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; "><span style="line-height: normal; ">首先按</span><span style="line-height: normal; ">c++</span><span style="line-height: normal; ">标准的话，</span><span style="line-height: normal; ">new</span><span style="line-height: normal; ">失败会抛出</span><span style="line-height: normal; ">bad_alloc</span><span style="line-height: normal; ">异常，但是有些编译器对</span><span style="line-height: normal; ">c++</span><span style="line-height: normal; ">标准支持不是很好，比如</span><span style="line-height: normal; ">vc++6.0</span><span style="line-height: normal; ">中</span><span style="line-height: normal; ">new</span><span style="line-height: normal; ">失败不会抛出异常，而返回</span><span style="line-height: normal; ">0.</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">//</span><span style="line-height: normal; ">不支持</span><span style="line-height: normal; ">c++</span><span style="line-height: normal; ">标准的做法如下</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">double *ptr=new double[1000000];</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">if( 0 == ptr)</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">&#8230;&#8230;处理失败&#8230;&#8230;</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">//</span><span style="line-height: normal; ">标准推荐做法一。</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">try</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">{</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">&nbsp;&nbsp;&nbsp;&nbsp;double *ptr=new double[1000000];</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">}</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">catch(bad_alloc &amp;memExp)</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">{</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">&nbsp;&nbsp;&nbsp;&nbsp;//</span><span style="line-height: normal; ">失败以后，要么</span><span style="line-height: normal; ">abort</span><span style="line-height: normal; ">要么重分配</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">&nbsp;&nbsp;&nbsp;&nbsp;cerr&lt;&lt;memExp.what()&lt;&lt;endl;</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">}</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">//</span><span style="line-height: normal; ">标准推荐做法二</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">是使用</span><span style="line-height: normal; ">set_new_handler</span><span style="line-height: normal; ">函数处理</span><span style="line-height: normal; ">new</span><span style="line-height: normal; ">失败。它在头文件</span><span style="line-height: normal; ">&lt;new&gt;</span><span style="line-height: normal; ">里大致是象下面这样定义的：</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">typedef void (*new_handler)();</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">new_handler set_new_handler(new_handler p) throw();</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 17.95pt; text-indent: 26.25pt; "><span style="line-height: normal; ">可以看到，</span><span style="line-height: normal; ">new_handler</span><span style="line-height: normal; ">是一个自定义的函数指针类型，它指向一个没有输入参数也没有返回值的函数。</span><span style="line-height: normal; ">set_new_handler</span><span style="line-height: normal; ">则是一个输入并返回</span><span style="line-height: normal; ">new_handler</span><span style="line-height: normal; ">类型的函数。</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 17.95pt; text-indent: 31.5pt; "><span style="line-height: normal; ">set_new_handler</span><span style="line-height: normal; ">的输入参数是</span><span style="line-height: normal; ">operator new</span><span style="line-height: normal; ">分配内存失败时要调用的出错处理函数的指针，返回值是</span><span style="line-height: normal; ">set_new_handler</span><span style="line-height: normal; ">没调用之前就已经在起作用的旧的出错处理函数的指针。</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">可以象下面这样使用</span><span style="line-height: normal; ">set_new_handler</span><span style="line-height: normal; ">：</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">// function to call if operator new can't allocate enough memory</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">void nomorememory()</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">{</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">cerr &lt;&lt; "unable to satisfy request for memory\n";</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">abort();</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">}</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">int main()</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">{</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">set_new_handler(nomorememory);</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">int *pbigdataarray = new int[100000000];</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">...</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">}</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">operator new</span><span style="line-height: normal; ">不能满足内存分配请求时，</span><span style="line-height: normal; ">new-handler</span><span style="line-height: normal; ">函数不只调用一次，而是不断重复，直至找到足够的内存。实现重复调用的代码在条款</span><span style="line-height: normal; ">8</span><span style="line-height: normal; ">里可以看到，这里我用描述性的的语言来说明：一个设计得好的</span><span style="line-height: normal; ">new-handler</span><span style="line-height: normal; ">函数必须实现下面功能中的一种。</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="line-height: normal; ">&#183;产生更多的可用内存。这将使</span><span style="line-height: normal; ">operator new</span><span style="line-height: normal; ">下一次分配内存的尝试有可能获得成功。实施这一策略的一个方法是：在程序启动时分配一个大的内存块，然后在第一次调用</span><span style="line-height: normal; ">new-handler</span><span style="line-height: normal; ">时释放。释放时伴随着一些对用户的警告信息，如内存数量太少，下次请求可能会失败，除非又有更多的可用空间。</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="line-height: normal; ">&#183;安装另一个不同的</span><span style="line-height: normal; ">new-handler</span><span style="line-height: normal; ">函数。如果当前的</span><span style="line-height: normal; ">new-handler</span><span style="line-height: normal; ">函数不能产生更多的可用内存，可能它会知道另一个</span><span style="line-height: normal; ">new-handler</span><span style="line-height: normal; ">函数可以提供更多的资源。这样的话，当前的</span><span style="line-height: normal; ">new-handler</span><span style="line-height: normal; ">可以安装另一个</span><span style="line-height: normal; ">new-handler</span><span style="line-height: normal; ">来取代它</span><span style="line-height: normal; ">(</span><span style="line-height: normal; ">通过调用</span><span style="line-height: normal; ">set_new_handler)</span><span style="line-height: normal; ">。下一次</span><span style="line-height: normal; ">operator new</span><span style="line-height: normal; ">调用</span><span style="line-height: normal; ">new-handler</span><span style="line-height: normal; ">时，会使用最近安装的那个。</span><span style="line-height: normal; ">(</span><span style="line-height: normal; ">这一策略的另一个变通办法是让</span><span style="line-height: normal; ">new-handler</span><span style="line-height: normal; ">可以改变它自己的运行行为，那么下次调用时，它将做不同的事。方法是使</span><span style="line-height: normal; ">new-handler</span><span style="line-height: normal; ">可以修改那些影响它自身行为的静态或全局数据。</span><span style="line-height: normal; ">)</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="line-height: normal; ">&#183;卸除</span><span style="line-height: normal; ">new-handler</span><span style="line-height: normal; ">。也就是传递空指针给</span><span style="line-height: normal; ">set_new_handler</span><span style="line-height: normal; ">。没有安装</span><span style="line-height: normal; ">new-handler</span><span style="line-height: normal; ">，</span><span style="line-height: normal; ">operator new</span><span style="line-height: normal; ">分配内存不成功时就会抛出一个标准的</span><span style="line-height: normal; ">std::bad_alloc</span><span style="line-height: normal; ">类型的异常。</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="line-height: normal; ">&#183;抛出</span><span style="line-height: normal; ">std::bad_alloc</span><span style="line-height: normal; ">或从</span><span style="line-height: normal; ">std::bad_alloc</span><span style="line-height: normal; ">继承的其他类型的异常。这样的异常不会被</span><span style="line-height: normal; ">operator new</span><span style="line-height: normal; ">捕捉，所以它们会被送到最初进行内存请求的地方。</span><span style="line-height: normal; ">(</span><span style="line-height: normal; ">抛出别的不同类型的异常会违反</span><span style="line-height: normal; ">operator new</span><span style="line-height: normal; ">异常规范。规范中的缺省行为是调用</span><span style="line-height: normal; ">abort</span><span style="line-height: normal; ">，所以</span><span style="line-height: normal; ">new-handler</span><span style="line-height: normal; ">要抛出一个异常时，一定要确信它是从</span><span style="line-height: normal; ">std::bad_alloc</span><span style="line-height: normal; ">继承来的。想更多地了解异常规范</span><span style="line-height: normal; ">)</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="line-height: normal; ">&#183;没有返回。典型做法是调用</span><span style="line-height: normal; ">abort</span><span style="line-height: normal; ">或</span><span style="line-height: normal; ">exit</span><span style="line-height: normal; ">。</span><span style="line-height: normal; ">abort/exit</span><span style="line-height: normal; ">可以在标准</span><span style="line-height: normal; ">c</span><span style="line-height: normal; ">库中找到</span><span style="line-height: normal; ">(</span><span style="line-height: normal; ">还有标准</span><span style="line-height: normal; ">c++</span><span style="line-height: normal; ">库</span><span style="line-height: normal; ">)</span><span style="line-height: normal; ">。</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; "></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">上面的选择给了你实现</span><span style="line-height: normal; ">new-handler</span><span style="line-height: normal; ">函数极大的灵活性。</span></p><p style="font-family: Tahoma, sans-serif; line-height: 22px; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 18pt; "><span style="line-height: normal; ">更多知识请参考《</span><span style="line-height: normal; ">Effective c++</span><span style="line-height: normal; ">》</span></p></div></td></tr></tbody></table>转自：<a href="http://hi.baidu.com/bellgrade/blog/item/dfff21259c12cf39c9955969.html">http://hi.baidu.com/bellgrade/blog/item/dfff21259c12cf39c9955969.html</a><img src ="http://www.cppblog.com/flyinghare/aggbug/178812.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2012-06-14 16:27 <a href="http://www.cppblog.com/flyinghare/archive/2012/06/14/178812.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>跑步的好处</title><link>http://www.cppblog.com/flyinghare/archive/2012/05/15/174954.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Tue, 15 May 2012 03:36:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2012/05/15/174954.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/174954.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2012/05/15/174954.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/174954.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/174954.html</trackback:ping><description><![CDATA[<span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">1.告别臃肿身材。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">许多人开始跑步就是因为减肥，跑步确实减肥的最好运动方式，跑步每分钟比起其他运动燃烧更多的卡路里。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">2.防止你的骨骼，肌肉退化。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">我们的骨骼是和你的身体需求相互协调的。长期坐在显示器前的我们让我们的骨骼越来越脆弱。而长期的，经常的运动会使你的骨骼保持健康。更进一步说就是防止我们身体内部老化的更快。经常的高强度锻炼，例如跑步，被证明可以促进人体荷尔蒙的生长，荷尔蒙就是那些名人为了看起来更年轻而持续注射的药剂。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">3.抵抗疾病&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">跑步可以降低得中风和乳腺癌的风险。经常的跑步已经成为医生对那些容易引发或在已经处在早期的骨质疏松，糖尿病，高血压病人的治疗建议。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">4.维持并提高总体的身体水平。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">跑步是是人们可以采取的最好的锻炼身体的运动。它可以提高胆固醇,降低血液凝块的危险，锻炼你的50%的经常处于闲置状态的肺。跑步还可以通过增加你的淋巴细胞来增强你的免疫力。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">5.让你更加自信。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">慢跑像其他一些单人运动一样，它可以增强你的自信心。跑步让你完成一次又一次的尝试，让你变得更强大，更加肯定自己。他让你真实的越过某个山峰，穿过某个障碍.在意识到你的身体已经更加强壮，更加有用，你会得到被赋予力量和自由的感觉。自信更是那些通过跑步成功的减肥并得到自己心中理想身材的跑步者的宝贵财富。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">6.放松自己，减轻压力。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">慢跑可以转移聂注意力，沐浴在路旁的风景中，你的烦恼一定会消失殆尽。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">长跑适合那些正处在一堆头疼，恼人的烦心事的人。还有比在两个小时的长跑中，清理的的头脑、舒缓自己的神经更好的主意了吗。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">如果你此时觉得异常压抑，何不快跑一下呢，之后你会一个好的心情。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">7.著名的&#8220;跑步者高峰体验&#8221;&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">包括释放压力，慢跑被证明提高你的心态。跑步，特别在户外和旅行中,会使身体释放一种物质让你产生一种幸福愉悦感（跑步者高峰体验）或者就是快乐的感觉。跑步已经被采用了多年来治疗临床抑郁症，上瘾等。更少的压力，更少的压抑，更少的疲劳，更少的混乱，经过一段时间的经常跑步，病人很快就有了变化。跑步让他们有了注意的对象，让他们看到了除了他们消极的状态和沉溺的事务，还有一些美好的东西的存在。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">8.锻炼你的头脑。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">像对你的身体有所帮助一样，跑步同样对你的头脑很有帮助。通过在跑步中克服一系列的障碍，你学会了专注和决心.在经历那些你几乎要放弃的长跑或其他项目后你会发现：你在跑步过程中产生的意志和体魄的增强让你在其他方面有着同样的专注和决心。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">9.增强合作精神。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">又是一个非常值得去做的好处。这点好处或许让很多人感到惊奇，因为人们认为跑步不可能得到这种益处，仅仅由于跑步是单人运动。但是跑步确实有时涉及到互相合作。旅行跑步，特别是在那些路况不好的地方，需要极大的合作意识。这些路面经常会有一些 障碍如石头、灌木让跑步进行的很困难。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">10.随时随地，简单。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">不是很多的运动可以在任何地方，几乎不需要设备的。我敢肯定古代希腊人会争辩说甚至是鞋子和衣服也不需要。今天，我们只是需要一双好点的跑步鞋然后就可以出发了。从市中心到郊区,整个世界的地方等待你的探索。经常出差吗？你的旅行箱里肯定会有空间来装你的运动鞋的。这个世界就是你的健身房，去再次发现它吧。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">Here are some tips for how to make running a practice:&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">Be consistent in your running program. Plan your weekly workout schedule and stick to it. This will teach you persistence.&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">Know which focuses you'll use during every run. This will teach you planning and mindfulness, and improve your mind/body connection.&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">Constantly practice relaxing your muscles. This will help to relieve tension and train you to relax no matter what activity you're doing.&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">At the end of your run, spend a few minutes doing an "end-of-run review." Ask yourself how well you did with keeping your focuses, how your body felt during the run. What did you come away with that will help your next run? Then, the next time you go out for a run, you'll have something to work on that you brought forward from your last run. In this way you'll build a healthy, growing and sustainable running program.&nbsp;</span>&nbsp;<br />转自：<a href="http://www.douban.com/group/topic/20749798/">http://www.douban.com/group/topic/20749798/</a><img src ="http://www.cppblog.com/flyinghare/aggbug/174954.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2012-05-15 11:36 <a href="http://www.cppblog.com/flyinghare/archive/2012/05/15/174954.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VS2010 关于 CVT1100 和 LNK1123 的解决办法</title><link>http://www.cppblog.com/flyinghare/archive/2012/02/21/166155.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Tue, 21 Feb 2012 10:01:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2012/02/21/166155.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/166155.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2012/02/21/166155.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/166155.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/166155.html</trackback:ping><description><![CDATA[<table style="table-layout: fixed; font-family: Arial;  width: 958px; ">
     <tbody>
         <tr>
             <td style="word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; font-size: 12px; line-height: 18px; ">
             <div id="blog_text" style="word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; overflow-x: hidden; overflow-y: hidden; position: relative !important; border-image: initial; ">错误提示：<br />
             Error&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp; error CVT1100: duplicate resource.&nbsp; type:MANIFEST, name:1, language:0x0409&nbsp;&nbsp;&nbsp;&nbsp;<br />
             Error&nbsp;&nbsp;&nbsp; 2&nbsp;&nbsp;&nbsp; error LNK1123: failure during conversion to COFF: file invalid or corrupt&nbsp;&nbsp;&nbsp;&nbsp;<br />
             MSDN 解决办法<br />
             //&nbsp; 打开工程的属性对话框<br />
             1.Open the project's Property Pages dialog box<br />
             // 点开连接<br />
             2.Click the Linker folder.&nbsp;<br />
             // 点击嵌套IDL&nbsp;<br />
             3.Click the Embedded IDL property page.&nbsp;<br />
             // 修改 TypeLib 资源ID 取 2 - 65535任一值<br />
             4.Modify the TypeLib Resource ID property.&nbsp;<br />
             若此未解决<br />
             请按下列步骤来进行<br />
             Project（工程） -&gt; Properties（属性） -&gt; Manifest Tool（清单工具） -&gt; Input and Output(输入及输出）-&gt; Embed Manifest (嵌套清单） -&gt;No<br />
             照此可解决问题</div>
             </td>
         </tr>
     </tbody>
</table>
转自 ：<a href="http://hi.baidu.com/qiylei/blog/item/7ebcecf4bbf3afe37609d7ee.html">http://hi.baidu.com/qiylei/blog/item/7ebcecf4bbf3afe37609d7ee.html</a><img src ="http://www.cppblog.com/flyinghare/aggbug/166155.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2012-02-21 18:01 <a href="http://www.cppblog.com/flyinghare/archive/2012/02/21/166155.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>控制全局变量初始化顺序 &amp;&amp; #pragma详解</title><link>http://www.cppblog.com/flyinghare/archive/2012/02/10/165280.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Fri, 10 Feb 2012 04:35:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2012/02/10/165280.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/165280.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2012/02/10/165280.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/165280.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/165280.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 文件的尾部或者出现对同一个内含函数指定intrinsic编译指示。function编译指示只能用于函数外&#8212;&#8212;在全局层次。为了列出具有内含形式的函数表，参见#pragma&nbsp;intrinsic。11 &nbsp;hdrstop#pragma&nbsp;hdrstop [( "filename" )]&nbsp;控制预编译头文件的工作方式。filename是要使用或者创...&nbsp;&nbsp;<a href='http://www.cppblog.com/flyinghare/archive/2012/02/10/165280.html'>阅读全文</a><img src ="http://www.cppblog.com/flyinghare/aggbug/165280.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2012-02-10 12:35 <a href="http://www.cppblog.com/flyinghare/archive/2012/02/10/165280.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>_variant_t 的 IUnknown* 操作符怪异行为</title><link>http://www.cppblog.com/flyinghare/archive/2012/01/18/164329.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Wed, 18 Jan 2012 03:58:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2012/01/18/164329.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/164329.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2012/01/18/164329.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/164329.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/164329.html</trackback:ping><description><![CDATA[&nbsp; &nbsp; &nbsp;刚才修改UI编辑器一个小功能，莫名其妙出现内存泄露。经过跟踪，发现是&nbsp;_variant_t 在捣鬼，来看这句代码：<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 />--><span style="color: #008080; ">1</span>&nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">bool</span>&nbsp;AddToCollection(IUnknown&nbsp;*lpiFile);<br /><span style="color: #008080; ">2</span>&nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">bool</span>&nbsp;AddToCollection(VARIANT &amp;varFile);<br /><span style="color: #008080; ">3</span>&nbsp; &nbsp;&nbsp;_variant_t&nbsp;GetDSFile();<br /><span style="color: #008080; ">4</span>&nbsp;<br /><span style="color: #008080; ">5</span>&nbsp; &nbsp;&nbsp;AddToCollection(GetDSFile());&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;这句将导致内存泄露！</span></div><br />&nbsp; &nbsp; &nbsp;初看没什么问题，但上面的代码最后一句将的确导致内存泄露！<br />&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 />--><span style="color: #008080; ">1</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">bool</span>&nbsp;AddToCollection(IUnknown&nbsp;*lpiFile);<br /><span style="color: #008080; ">2</span>&nbsp; &nbsp; &nbsp;<span style="color: #0000ff; ">bool</span>&nbsp;AddToCollection(VARIANT &amp;varFile);&nbsp;<br /><span style="color: #008080; ">3</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_variant_t&nbsp;GetDSFile();<br /><span style="color: #008080; ">4</span>&nbsp;<br /><span style="color: #008080; ">5</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_variant_t&nbsp;varFile&nbsp;=&nbsp;GetDSFile();<br /><span style="color: #008080; ">6</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddToCollection(varFile);&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;正常！</span></div><br />&nbsp; &nbsp; &nbsp; 进一步跟踪发现，第一种方式调用的&nbsp;<span style="font-size: 13px; background-color: #eeeeee; ">AddToCollection(IUnknown&nbsp;*lpiFile)</span>&nbsp;，检查 _variant_t 的重载代码如下：<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 />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Extracts&nbsp;a&nbsp;VT_UNKNOWN&nbsp;into&nbsp;an&nbsp;IUnknown*<br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #008000; "></span><span style="color: #008000; ">//<br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #008000; "></span>inline&nbsp;_variant_t::<span style="color: #0000FF; ">operator</span>&nbsp;IUnknown*()&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;<br /><span style="color: #008080; ">&nbsp;4</span>&nbsp;{<br /><span style="color: #008080; ">&nbsp;5</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(V_VT(<span style="color: #0000FF; ">this</span>)&nbsp;==&nbsp;VT_UNKNOWN)&nbsp;{<br /><span style="color: #008080; ">&nbsp;6</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(V_UNKNOWN(<span style="color: #0000FF; ">this</span>)&nbsp;!=&nbsp;NULL)&nbsp;{<br /><span style="color: #008080; ">&nbsp;7</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;V_UNKNOWN(<span style="color: #0000FF; ">this</span>)-&gt;AddRef();&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;就是这里增加了引用计数</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">&nbsp;9</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;V_UNKNOWN(<span style="color: #0000FF; ">this</span>);<br /><span style="color: #008080; ">10</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">11</span>&nbsp;<br /><span style="color: #008080; ">12</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_variant_t&nbsp;varDest;<br /><span style="color: #008080; ">13</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;varDest.ChangeType(VT_UNKNOWN,&nbsp;<span style="color: #0000FF; ">this</span>);<br /><span style="color: #008080; ">14</span>&nbsp;<br /><span style="color: #008080; ">15</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(V_UNKNOWN(&amp;varDest)&nbsp;!=&nbsp;NULL)&nbsp;{<br /><span style="color: #008080; ">16</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;V_UNKNOWN(&amp;varDest)-&gt;AddRef();&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;就是这里增加了引用计数</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">17</span>&nbsp;<span style="color: #008000; "></span>&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #008080; ">18</span>&nbsp;<br /><span style="color: #008080; ">19</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;V_UNKNOWN(&amp;varDest);<br /><span style="color: #008080; ">20</span>&nbsp;}</div><br />&nbsp; &nbsp; &nbsp; 注意到，上面的代码中有两处增加了引用计数！<br />&nbsp; &nbsp; &nbsp; 问题就出在这里！<br />&nbsp; &nbsp; &nbsp; 一般来讲，从函数返回值返回的 COM 指针是不增加引用计数的，如果调用者需要持有该指针，由调用者自己增加引用计数即可，<span style="color: red; ">但不知为何，这里会增加引用计数，不解！！！！！<br /><br /></span><span>&nbsp; &nbsp; &nbsp; 另外&nbsp;</span>
<span style="font-size: 13px; background-color: #eeeeee; ">GetDSFile() 返回的是 _variant_t ，为什么编译器要去调用&nbsp;</span>
<span style="font-size: 13px; background-color: #eeeeee; ">AddToCollection(IUnknown&nbsp;*lpiFile)</span>&nbsp;？ &nbsp;其实是因为&nbsp;<span style="font-size: 13px; background-color: #eeeeee; ">GetDSFile()</span>&nbsp;返回的是临时变量，临时变量优先匹配 const 的重载，所以将&nbsp;<span style="font-size: 13px; background-color: #eeeeee; color: #0000ff; ">bool</span><span style="font-size: 13px; background-color: #eeeeee; ">&nbsp;AddToCollection(VARIANT &amp;varFile);</span>&nbsp;改成&nbsp;<span style="font-size: 13px; background-color: #eeeeee; color: #0000ff; ">bool</span><span style="font-size: 13px; background-color: #eeeeee; ">&nbsp;AddToCollection(</span><span style="font-size: 13px; background-color: #eeeeee; color: #ff0000; ">const</span><span style="font-size: 13px; background-color: #eeeeee; "> VARIANT &amp;varFile);</span>&nbsp;也可以！！<br /><br /><img src ="http://www.cppblog.com/flyinghare/aggbug/164329.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2012-01-18 11:58 <a href="http://www.cppblog.com/flyinghare/archive/2012/01/18/164329.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用C++模板元编程对类型进行静态分离</title><link>http://www.cppblog.com/flyinghare/archive/2011/08/04/152442.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Thu, 04 Aug 2011 07:24:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2011/08/04/152442.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/152442.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2011/08/04/152442.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/152442.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/152442.html</trackback:ping><description><![CDATA[<span class="Apple-style-span" style="color: #48352f; font-family: Georgia; font-size: 12px; letter-spacing: 2px; line-height: 20px; background-color: #ece6d0; ">&nbsp; &nbsp; &nbsp; &nbsp;前段时间仿照虚幻3写ConfigFile，有两个重要的需求，其一是快速的搜索配置文件中的Key_Value_pair;其二是可以还原到读入时的状态，或者友好串行化。很明显，要做到快速的搜索需要用二叉树或者散列表来帮忙，但是如果直接用map或者hash_map都不行，会破坏输入顺序，以下面的例子为例：<br style="line-height: normal; " />key1=1<br style="line-height: normal; " />key0=0<br style="line-height: normal; " />key2=2<br style="line-height: normal; " />那么实际上在map中的顺序是0 1 2，因此破坏了顺序，如果要达到还原的效果，则需要自己使用vector来保存输入的顺序，那么这会造成很大的负担，特别是在出现删除的时候。<br style="line-height: normal; " />不过还好，强大的boost提供了multi_index库，我们可以使用它来对同一个容器提供两个不同的视图(View)，一个有序一个只是个普通序列。<br style="line-height: normal; " />再考虑到字符编码、大小写敏感和是否支持重复Key_value_pair，可以得到这样的一个声明：<br style="line-height: normal; " />template &lt; typename TCHARTYPE, bool bCaseSensitive, bool bMulti &gt;<br style="line-height: normal; " />class config_info;<br style="line-height: normal; " />对于bCaseSensitive，我们需要对算法进行分派，使得总是能够调用到正确的算法比如strcmp和stricmp，这需要通过特化来做到。<br style="line-height: normal; " />是否支持重复键，可以用map和multimap来区分。<br style="line-height: normal; " />这些都可以用特化来做，不过如果是这样的话，那么对于顶级类config_info来说，规模会是指数膨胀，这时候需要Traits的帮助，这样我们把不同的部分都放到Traits类中，将相同的部分放到config_info当中。<br style="line-height: normal; " />因此，我们可以得到大概这样一个类，以下是代码片段：<br style="line-height: normal; " />template &lt; typename TCHARTYPE, bool bCaseSensitive, bool bMulti &gt;<br style="line-height: normal; " />class config_info<br style="line-height: normal; " />{<br style="line-height: normal; " />protected:<br style="line-height: normal; " /><font color="#ff00ff" style="line-height: normal; ">typedef boost::multi_index::multi_index_container&lt;<br style="line-height: normal; " />section_info&lt; TCHARTYPE, bCaseSensitive, false &gt;,<br style="line-height: normal; " />boost::multi_index::indexed_by&lt;&nbsp;<br style="line-height: normal; " />boost::multi_index::ordered_unique&lt;&nbsp;<br style="line-height: normal; " />boost::multi_index::identity&lt;&nbsp;<br style="line-height: normal; " />section_info&lt; TCHARTYPE, bCaseSensitive, false &gt;&nbsp;<br style="line-height: normal; " />&gt;&nbsp;<br style="line-height: normal; " />&gt;,<br style="line-height: normal; " />boost::multi_index::sequenced&lt;&gt;<br style="line-height: normal; " />&gt;<br style="line-height: normal; " />&gt; single_container_type;<br style="line-height: normal; " /><br style="line-height: normal; " />typedef boost::multi_index::multi_index_container&lt;<br style="line-height: normal; " />section_info&lt; TCHARTYPE, bCaseSensitive, true &gt;,<br style="line-height: normal; " />boost::multi_index::indexed_by&lt;&nbsp;<br style="line-height: normal; " />boost::multi_index::ordered_non_unique&lt;&nbsp;<br style="line-height: normal; " />boost::multi_index::identity&lt;&nbsp;<br style="line-height: normal; " />section_info&lt; TCHARTYPE, bCaseSensitive, true &gt;&nbsp;<br style="line-height: normal; " />&gt;&nbsp;<br style="line-height: normal; " />&gt;,<br style="line-height: normal; " />boost::multi_index::sequenced&lt;&gt;<br style="line-height: normal; " />&gt;<br style="line-height: normal; " />&gt; multi_container_type;<br style="line-height: normal; " /><br style="line-height: normal; " />public:<br style="line-height: normal; " />typedef typename boost::mpl::if_c&lt; bMulti, multi_container_type, single_container_type &gt;::type&nbsp;&nbsp; container_type;</font><br style="line-height: normal; " /><br style="line-height: normal; " />typedef typename container_type::nth_index&lt;0&gt;::type&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; first_view_type;<br style="line-height: normal; " />typedef typename container_type::nth_index&lt;1&gt;::type&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; second_view_type;<br style="line-height: normal; " />typedef typename first_view_type::const_iterator&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ordered_const_iterator;<br style="line-height: normal; " />typedef typename second_view_type::const_iterator&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; non_ordered_const_iterator;<br style="line-height: normal; " />typedef std::pair&lt; ordered_const_iterator, ordered_const_iterator &gt;&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;&nbsp; ordered_const_iterator_range;<br style="line-height: normal; " /><br style="line-height: normal; " /><br style="line-height: normal; " /><font color="#00ff00" style="line-height: normal; ">typedef detail::config_info_provider_traits&lt;TCHARTYPE&gt;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; provider_traits;<br style="line-height: normal; " />typedef detail::config_info_string_algorithm&lt;bCaseSensitive&gt;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string_algorithm;</font><br style="line-height: normal; " /><br style="line-height: normal; " />typedef std::vector&lt; TCHARTYPE &gt;&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffer_type;<br style="line-height: normal; " />typedef section_info&lt; TCHARTYPE, bCaseSensitive, bMulti &gt;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; section_type;<br style="line-height: normal; " /><br style="line-height: normal; " />// 这样可以更好的利用IDE的Intellisense<br style="line-height: normal; " />typedef std::basic_string&lt;TCHARTYPE&gt;&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;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; string_type;<br style="line-height: normal; " />typedef typename section_type::value_type&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;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value_type;<br style="line-height: normal; " />typedef typename section_type::key_type&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;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; key_type;<br style="line-height: normal; " />typedef typename section_type::key_value_type&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;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; key_value_type;<br style="line-height: normal; " /><br style="line-height: normal; " />这里我直接使用了boost.mpl来实现静态分离(<font color="#9900ff" style="line-height: normal; ">不好意思，我不知道怎么描述，这个词汇是我自己想出来的，不知道准确不准确，请原谅我大言不惭的为它定义，即：通过某种方法，在编译时选择正确的类</font>。<span style="line-height: normal; background-color: #ffe599; ">如果您知道怎么正确描述这种行为，请告诉我，谢谢。<img src="http://img.baidu.com/hi/jx2/j_0016.gif" style="line-height: normal; "  alt="" /></span>）。<br style="line-height: normal; " />如果你觉得上面typedef太多、嵌套层次太深的话，请看下面的微缩版代码：<br style="line-height: normal; " />#include &lt;iostream&gt;<br style="line-height: normal; " />#include &lt;set&gt;<br style="line-height: normal; " />using namespace std;<br style="line-height: normal; " /><br style="line-height: normal; " /><font color="#444444" style="line-height: normal; ">namespace mpl<br style="line-height: normal; " />{<br style="line-height: normal; " />template &lt; bool bCondition, typename T1, typename T2 &gt;<br style="line-height: normal; " />struct _if<br style="line-height: normal; " />{&nbsp;&nbsp;&nbsp;&nbsp;<br style="line-height: normal; " />typedef void type;<br style="line-height: normal; " />};<br style="line-height: normal; " /><br style="line-height: normal; " />template &lt; typename T1, typename T2 &gt;<br style="line-height: normal; " />struct _if&lt; true, T1, T2 &gt;<br style="line-height: normal; " />{<br style="line-height: normal; " />typedef T1 type;<br style="line-height: normal; " />};<br style="line-height: normal; " /><br style="line-height: normal; " />template &lt; typename T1, typename T2 &gt;<br style="line-height: normal; " />struct _if&lt; false, T1, T2 &gt;<br style="line-height: normal; " />{<br style="line-height: normal; " />typedef T2 type;<br style="line-height: normal; " />};<br style="line-height: normal; " />}</font><br style="line-height: normal; " /><br style="line-height: normal; " />#pragma pack(1) // 不对齐<br style="line-height: normal; " /><br style="line-height: normal; " />template &lt; typename T, bool bMulti &gt;<br style="line-height: normal; " />class TestContainer<br style="line-height: normal; " />{<br style="line-height: normal; " />// msstl下面它们大小都是28 (对于int来说)<br style="line-height: normal; " />typedef std::set&lt; T &gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; single_type;<br style="line-height: normal; " />typedef std::multiset&lt;T&gt;&nbsp;&nbsp; multi_type;<br style="line-height: normal; " /><br style="line-height: normal; " />// dummy只用来演示类大小的不同<br style="line-height: normal; " />typedef char&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; single_dummy; // 不对齐的时候字节数是1<br style="line-height: normal; " />typedef double&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; multi_dummy;&nbsp;&nbsp; // 不对齐的时候字节数是8<br style="line-height: normal; " />typedef typename mpl::_if&lt; bMulti, multi_dummy, single_dummy &gt;::type dummy_type;<br style="line-height: normal; " />public:&nbsp;<br style="line-height: normal; " />typedef typename mpl::_if&lt; bMulti, multi_type, single_type &gt;::type&nbsp;&nbsp; set_type;<br style="line-height: normal; " /><br style="line-height: normal; " />public:<br style="line-height: normal; " />void insert( const T&amp; t )<br style="line-height: normal; " />{<br style="line-height: normal; " />m_set.insert( t );<br style="line-height: normal; " />}<br style="line-height: normal; " /><br style="line-height: normal; " />void print() const<br style="line-height: normal; " />{<br style="line-height: normal; " />for( set_type::const_iterator it = m_set.begin();<br style="line-height: normal; " />it != m_set.end();<br style="line-height: normal; " />++it )<br style="line-height: normal; " />{<br style="line-height: normal; " />cout&lt;&lt; *it &lt;&lt;" ";<br style="line-height: normal; " />}<br style="line-height: normal; " />cout&lt;&lt; endl;<br style="line-height: normal; " />}<br style="line-height: normal; " />private:<br style="line-height: normal; " />set_type m_set;<br style="line-height: normal; " /><br style="line-height: normal; " />dummy_type m_dummy;<br style="line-height: normal; " />};<br style="line-height: normal; " /><br style="line-height: normal; " /><br style="line-height: normal; " />int main()<br style="line-height: normal; " />{<br style="line-height: normal; " />{<br style="line-height: normal; " />cout&lt;&lt; "TestContainer&lt;int, true&gt; : " &lt;&lt; sizeof(TestContainer&lt;int, true&gt;) &lt;&lt; endl;<br style="line-height: normal; " /><br style="line-height: normal; " />TestContainer&lt;int, true&gt; t;<br style="line-height: normal; " />t.insert( 100 );<br style="line-height: normal; " />t.insert( 100 );<br style="line-height: normal; " />t.insert( 200 );<br style="line-height: normal; " />t.insert( 200 );<br style="line-height: normal; " />t.insert( 200 );<br style="line-height: normal; " />t.print();<br style="line-height: normal; " />}<br style="line-height: normal; " /><br style="line-height: normal; " />{<br style="line-height: normal; " />cout&lt;&lt; "TestContainer&lt;int, false&gt; : " &lt;&lt; sizeof(TestContainer&lt;int, false&gt;) &lt;&lt; endl;<br style="line-height: normal; " /><br style="line-height: normal; " />TestContainer&lt;int, false&gt; t;<br style="line-height: normal; " />t.insert( 100 );<br style="line-height: normal; " />t.insert( 100 );<br style="line-height: normal; " />t.insert( 200 );<br style="line-height: normal; " />t.insert( 200 );<br style="line-height: normal; " />t.insert( 200 );<br style="line-height: normal; " />t.print();<br style="line-height: normal; " />}<br style="line-height: normal; " /><br style="line-height: normal; " /><br style="line-height: normal; " />return 0;<br style="line-height: normal; " />}<br style="line-height: normal; " /><br style="line-height: normal; " />输出结果是：<br style="line-height: normal; " />TestContainer&lt;int, true&gt; : 36<br style="line-height: normal; " />100 100 200 200 200<br style="line-height: normal; " />TestContainer&lt;int, false&gt; : 29<br style="line-height: normal; " />100 200<br style="line-height: normal; " />请按任意键继续. . .<br style="line-height: normal; " />根据是否支持重复，bMulti是否为真，通过一点模板元的代码可以让编译器自动选择正确的容器。当然前提是bMulti必须是在编译时就能确定的值。如果是变量，要通过变量来选择正确的类的话，则是动态的，如果你愿意，可以称为动态分离（<font color="#000000" style="line-height: normal; background-color: #ead1dc; ">&#8857;﹏&#8857;b汗，不要倒，你要淡定。<img src="http://img.baidu.com/hi/jx2/j_0020.gif" style="line-height: normal; "  alt="" /></font>）。<br style="line-height: normal; " /><br style="line-height: normal; " />boost.mpl提供了大量的、强大的和令人钦佩的模板元编程库。说到底，这都依赖于编译器，依赖于模板特化，包括使用模板元计算斐波那契数列亦是如此，让人不得不佩服C++的伟大。<br style="line-height: normal; " />以上面的简单例子为例，那么我们可以知道，当bMulti的值不同的时候，编译器会自动得到不同的type。<br style="line-height: normal; " />回到config_info，两行绿色的代码做的事情就是把变化提取出来，然后这样的好处在于我在config_info里面总是能够用同样的接口做不同的事情。以序列化为例：<br style="line-height: normal; " />inline void serialize( buffer_type&amp; buf ) const<br style="line-height: normal; " />{<br style="line-height: normal; " />// 序列化所有的注释<br style="line-height: normal; " />comment_container::const_iterator itRight = m_comments.end();<br style="line-height: normal; " /><br style="line-height: normal; " />for( comment_container::const_iterator it = m_comments.begin();<br style="line-height: normal; " />it != m_comments.end();<br style="line-height: normal; " />++it )<br style="line-height: normal; " />{<br style="line-height: normal; " />if( it-&gt;m_ePos == comment_type::ECP_RIGHT )<br style="line-height: normal; " />{<br style="line-height: normal; " />itRight = it;<br style="line-height: normal; " />continue;<br style="line-height: normal; " />}<br style="line-height: normal; " />else<br style="line-height: normal; " />{<br style="line-height: normal; " />buf.push_back(&nbsp;<span style="line-height: normal; background-color: #ff9900; ">provider_traits::standard_comment_char() )</span>;<br style="line-height: normal; " />buf.push_back(&nbsp;<span style="line-height: normal; background-color: #ff9900; ">provider_traits::standard_space_char()&nbsp;</span>);<br style="line-height: normal; " />buf.insert( buf.end(), it-&gt;m_strInfo.begin(), it-&gt;m_strInfo.end() );<br style="line-height: normal; " />buf.push_back(&nbsp;<font color="#ff9900" style="line-height: normal; ">provider_traits::return_char()&nbsp;</font>);<br style="line-height: normal; " />}<br style="line-height: normal; " />}<br style="line-height: normal; " /><br style="line-height: normal; " />// 序列化section<br style="line-height: normal; " />buf.push_back( TCHARTYPE('[') );<br style="line-height: normal; " />buf.insert( buf.end(), m_strSectionName.begin(), m_strSectionName.end() );<br style="line-height: normal; " />buf.push_back(&nbsp;<span style="line-height: normal; background-color: #8e7cc3; ">TCHARTYPE(']')&nbsp;</span>); //&nbsp;<font color="#000000" style="line-height: normal; background-color: #00ffff; ">不要对这个感到意外，因为我太懒了，还没调整，应该改到Traits中去的，当然对于char和wchar_t来说，这会工作正常。</font><br style="line-height: normal; " /><br style="line-height: normal; " />if( itRight != m_comments.end() )<br style="line-height: normal; " />{<br style="line-height: normal; " />buf.push_back(&nbsp;<span style="line-height: normal; background-color: #ff9900; ">provider_traits::standard_space_char()&nbsp;</span>);<br style="line-height: normal; " />buf.push_back(&nbsp;<span style="line-height: normal; background-color: #ff9900; ">provider_traits::standard_comment_char()</span>&nbsp;);<br style="line-height: normal; " />buf.insert( buf.end(), itRight-&gt;m_strInfo.begin(), itRight-&gt;m_strInfo.end() );<br style="line-height: normal; " />}<br style="line-height: normal; " /><br style="line-height: normal; " />buf.push_back(&nbsp;<font color="#ff9900" style="line-height: normal; ">provider_traits::return_char()&nbsp;</font>);<br style="line-height: normal; " /><br style="line-height: normal; " />for( second_view_type::const_iterator it = m_Con.get&lt;1&gt;().begin();<br style="line-height: normal; " />it != m_Con.get&lt;1&gt;().end();<br style="line-height: normal; " />++it )<br style="line-height: normal; " />{<br style="line-height: normal; " />it-&gt;serialize( buf );<br style="line-height: normal; " />}<br style="line-height: normal; " />}<br style="line-height: normal; " />再看看这个provider_traits的定义你就明白了：<br style="line-height: normal; " />/**<br style="line-height: normal; " />* @brief 提供用於提供不同字符串編碼的標準信息<br style="line-height: normal; " />*/<br style="line-height: normal; " />template &lt; typename TCHARTYPE &gt;<br style="line-height: normal; " />class config_info_provider_traits<br style="line-height: normal; " />{<br style="line-height: normal; " />public:<br style="line-height: normal; " />typedef std::basic_string&lt;TCHARTYPE&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string_type;<br style="line-height: normal; " />public:<br style="line-height: normal; " />static const TCHARTYPE* comments_string();<br style="line-height: normal; " />static const TCHARTYPE return_char();<br style="line-height: normal; " />static const TCHARTYPE standard_comment_char();<br style="line-height: normal; " />static const TCHARTYPE standard_space_char();<br style="line-height: normal; " />static const TCHARTYPE* null_string();<br style="line-height: normal; " />static const TCHARTYPE equals_sign();<br style="line-height: normal; " />};<br style="line-height: normal; " /><br style="line-height: normal; " />template &lt;&gt;<br style="line-height: normal; " />class config_info_provider_traits&lt;char&gt;<br style="line-height: normal; " />{<br style="line-height: normal; " />public:<br style="line-height: normal; " />typedef std::basic_string&lt;char&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string_type;<br style="line-height: normal; " />public:<br style="line-height: normal; " />static const char* comments_string()<br style="line-height: normal; " />{<br style="line-height: normal; " />return ";#";<br style="line-height: normal; " />}<br style="line-height: normal; " /><br style="line-height: normal; " />static const char return_char()<br style="line-height: normal; " />{<br style="line-height: normal; " />return '\n';<br style="line-height: normal; " />}<br style="line-height: normal; " /><br style="line-height: normal; " />static const char standard_comment_char()<br style="line-height: normal; " />{<br style="line-height: normal; " />return ';';<br style="line-height: normal; " />}<br style="line-height: normal; " /><br style="line-height: normal; " />static const char standard_space_char()<br style="line-height: normal; " />{<br style="line-height: normal; " />return ' ';<br style="line-height: normal; " />}&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<br style="line-height: normal; " /><br style="line-height: normal; " />static const char* null_string()<br style="line-height: normal; " />{<br style="line-height: normal; " />return "";<br style="line-height: normal; " />}<br style="line-height: normal; " /><br style="line-height: normal; " />static const char equals_sign()<br style="line-height: normal; " />{<br style="line-height: normal; " />return '=';<br style="line-height: normal; " />}<br style="line-height: normal; " />};<br style="line-height: normal; " /><br style="line-height: normal; " />template &lt;&gt;<br style="line-height: normal; " />class config_info_provider_traits&lt;wchar_t&gt;<br style="line-height: normal; " />{<br style="line-height: normal; " />public:<br style="line-height: normal; " />typedef std::basic_string&lt;wchar_t&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string_type;<br style="line-height: normal; " />public:<br style="line-height: normal; " />static const wchar_t* comments_string()<br style="line-height: normal; " />{<br style="line-height: normal; " />return L";#";<br style="line-height: normal; " />}<br style="line-height: normal; " /><br style="line-height: normal; " />static const wchar_t return_char()<br style="line-height: normal; " />{<br style="line-height: normal; " />return L'\n';<br style="line-height: normal; " />}<br style="line-height: normal; " /><br style="line-height: normal; " />static const wchar_t standard_comment_char()<br style="line-height: normal; " />{<br style="line-height: normal; " />return L';';<br style="line-height: normal; " />}<br style="line-height: normal; " /><br style="line-height: normal; " />static const wchar_t standard_space_char()<br style="line-height: normal; " />{<br style="line-height: normal; " />return L' ';<br style="line-height: normal; " />}<br style="line-height: normal; " /><br style="line-height: normal; " />static const wchar_t* null_string()<br style="line-height: normal; " />{<br style="line-height: normal; " />return L"";<br style="line-height: normal; " />}<br style="line-height: normal; " /><br style="line-height: normal; " />static const wchar_t equals_sign()<br style="line-height: normal; " />{<br style="line-height: normal; " />return L'=';<br style="line-height: normal; " />}<br style="line-height: normal; " />};<br style="line-height: normal; " />字符串算法部分：<br style="line-height: normal; " />/**<br style="line-height: normal; " />* @brief 用于分发算法 使用C库函数优化字符串比较操作<br style="line-height: normal; " />*/<br style="line-height: normal; " />template &lt; typename TCHARTYPE &gt;<br style="line-height: normal; " />class std_basic_string_algorithm<br style="line-height: normal; " />{<br style="line-height: normal; " />public:<br style="line-height: normal; " />inline static bool equals(&nbsp;<br style="line-height: normal; " />const std::basic_string&lt;TCHARTYPE&gt;&amp; Input,<br style="line-height: normal; " />const std::basic_string&lt;TCHARTYPE&gt;&amp; Test )<br style="line-height: normal; " />{<br style="line-height: normal; " />return 0 == std::char_traits&lt;TCHARTYPE&gt;::compare( Input.c_str(), Test.c_str() );<br style="line-height: normal; " />}<br style="line-height: normal; " /><br style="line-height: normal; " />inline static bool iequals(&nbsp;<br style="line-height: normal; " />const std::basic_string&lt;TCHARTYPE&gt;&amp; Input,<br style="line-height: normal; " />const std::basic_string&lt;TCHARTYPE&gt;&amp; Test );<br style="line-height: normal; " /><br style="line-height: normal; " />inline static bool lexicographical_compare(&nbsp;<br style="line-height: normal; " />const std::basic_string&lt;TCHARTYPE&gt;&amp; Input,<br style="line-height: normal; " />const std::basic_string&lt;TCHARTYPE&gt;&amp; Test )<br style="line-height: normal; " />{<br style="line-height: normal; " />return std::char_traits&lt;TCHARTYPE&gt;::compare( Input.c_str(), Test.c_str() ) &lt; 0;<br style="line-height: normal; " />}<br style="line-height: normal; " /><br style="line-height: normal; " />inline static bool ilexicographical_compare(&nbsp;<br style="line-height: normal; " />const std::basic_string&lt;TCHARTYPE&gt;&amp; Input,<br style="line-height: normal; " />const std::basic_string&lt;TCHARTYPE&gt;&amp; Test );<br style="line-height: normal; " />};<br style="line-height: normal; " />我使用strcmp、stricmp、wcscmp、wcsicmp在char和wchar_t的特化类中优化这些算法。<br style="line-height: normal; " />我使用下面这个类来分离大小写是否敏感：<br style="line-height: normal; " />/**<br style="line-height: normal; " />* @brief 用于分离字符串在是否大小写敏感的状态下的算法<br style="line-height: normal; " />*/<br style="line-height: normal; " />template &lt; bool bCaseSensitive &gt;<br style="line-height: normal; " />class config_info_string_algorithm<br style="line-height: normal; " />{<br style="line-height: normal; " />public:<br style="line-height: normal; " />template&lt;typename Range1T, typename Range2T&gt;<br style="line-height: normal; " />inline static bool equals(&nbsp;<br style="line-height: normal; " />const Range1T&amp; Input,&nbsp;<br style="line-height: normal; " />const Range2T&amp; Test);<br style="line-height: normal; " /><br style="line-height: normal; " />template&lt;typename Range1T, typename Range2T&gt;<br style="line-height: normal; " />inline static bool lexicographical_compare(<br style="line-height: normal; " />const Range1T&amp; Arg1,<br style="line-height: normal; " />const Range2T&amp; Arg2 );<br style="line-height: normal; " />};<br style="line-height: normal; " />在特化类中它们分别会调用equals或者iequals等。<br style="line-height: normal; " /><br style="line-height: normal; " />如果你要问我为什么要用模板来写，我说这样很方便，而且效率也不会低：<br style="line-height: normal; " /><font color="#741b47" style="line-height: normal; ">typedef config_file&lt;char, false, false &gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char_config_file;<br style="line-height: normal; " />typedef config_file&lt;wchar_t, false, false &gt;&nbsp;&nbsp;&nbsp; wchar_config_file;<br style="line-height: normal; " />typedef config_file&lt;char, false, true &gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char_data_provider;<br style="line-height: normal; " />typedef config_file&lt;wchar_t, false, true &gt;&nbsp;&nbsp;&nbsp;&nbsp; wchar_data_provider;</font><br style="line-height: normal; " />我只需要4个typedef就可以得到4个完全不同的类，甚至通过更多的组合生成更多的类，何乐而不为呢？<br style="line-height: normal; " /><br style="line-height: normal; " />好了，朋友们有感兴趣的可以去看Boost的文档看mpl相关的东西。<br /><br /></span>转自：<a href="http://hi.baidu.com/_%E2d_%B7%B3_%DE%B2%C2%D2/blog/item/c399dc94029dbe12d31b7076.html">http://hi.baidu.com/_%E2d_%B7%B3_%DE%B2%C2%D2/blog/item/c399dc94029dbe12d31b7076.html</a><img src ="http://www.cppblog.com/flyinghare/aggbug/152442.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2011-08-04 15:24 <a href="http://www.cppblog.com/flyinghare/archive/2011/08/04/152442.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>获取成员变量类型</title><link>http://www.cppblog.com/flyinghare/archive/2011/08/04/152438.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Thu, 04 Aug 2011 05:55:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2011/08/04/152438.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/152438.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2011/08/04/152438.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/152438.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/152438.html</trackback:ping><description><![CDATA[<span class="Apple-style-span" style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff; "><p>这应该是模板元编程里的概念吧，有时候我们确实需要获取成员变量的类型，这里提供一个方法借助模板的偏特化达到目的：</p><p><span style="font-size: xx-small; "></span></p><div class="dp-highlighter bg_cpp" style="width: 687px; "><div class="bar"><div class="tools"><a href="http://blog.csdn.net/jadedrip/article/details/5583300#" class="ViewSource" title="view plain" style="background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); border-width: initial; border-color: initial; padding-top: 1px; padding-right: 1px; padding-bottom: 1px; padding-left: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-position: 0% 0%; background-repeat: no-repeat no-repeat; ">view plain</a></div></div><ol start="1" class="dp-cpp" style="border-width: initial; border-color: initial; "><li class="alt" style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; "><span class="keyword" style="border-width: initial; border-color: initial; ">template</span><span style="border-width: initial; border-color: initial; ">&lt;&nbsp;</span><span class="keyword" style="border-width: initial; border-color: initial; ">typename</span><span style="border-width: initial; border-color: initial; ">&nbsp;P&gt;&nbsp;&nbsp;</span></span></li><li class="" style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; "><span class="keyword" style="border-width: initial; border-color: initial; ">struct</span><span style="border-width: initial; border-color: initial; ">&nbsp;MemberType;&nbsp;&nbsp;</span></span></li><li class="alt" style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; "><span class="keyword" style="border-width: initial; border-color: initial; ">template</span><span style="border-width: initial; border-color: initial; ">&lt;&nbsp;</span><span class="keyword" style="border-width: initial; border-color: initial; ">typename</span><span style="border-width: initial; border-color: initial; ">&nbsp;F,&nbsp;</span><span class="keyword" style="border-width: initial; border-color: initial; ">typename</span><span style="border-width: initial; border-color: initial; ">&nbsp;T&nbsp;&gt;&nbsp;&nbsp;</span></span></li><li class="" style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; "><span class="keyword" style="border-width: initial; border-color: initial; ">struct</span><span style="border-width: initial; border-color: initial; ">&nbsp;MemberType&lt;&nbsp;F&nbsp;T::*&nbsp;&gt;&nbsp;&nbsp;</span></span></li><li class="alt" style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">{&nbsp;&nbsp;</span></li><li class="" style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword" style="border-width: initial; border-color: initial; ">typedef</span><span style="border-width: initial; border-color: initial; ">&nbsp;F&nbsp;member_type;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt" style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword" style="border-width: initial; border-color: initial; ">typedef</span><span style="border-width: initial; border-color: initial; ">&nbsp;T&nbsp;class_type;&nbsp;&nbsp;</span></span></li><li class="" style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">};&nbsp;&nbsp;</span></li></ol></div>&nbsp;</span><p>&nbsp;</p><p>假设我们有个结构定义如下：</p><p>&nbsp;</p><div class="dp-highlighter bg_cpp" style="width: 687px; "><div class="bar"><div class="tools"><a href="http://blog.csdn.net/jadedrip/article/details/5583300#" class="ViewSource" title="view plain" style="background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); border-width: initial; border-color: initial; padding-top: 1px; padding-right: 1px; padding-bottom: 1px; padding-left: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-position: 0% 0%; background-repeat: no-repeat no-repeat; ">view plain</a></div></div><ol start="1" class="dp-cpp" style="border-width: initial; border-color: initial; "><li class="alt" style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; "><span class="keyword" style="border-width: initial; border-color: initial; ">struct</span><span style="border-width: initial; border-color: initial; ">&nbsp;Call&nbsp;&nbsp;</span></span></li><li class="" style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li class="alt" style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">&nbsp;&nbsp;&nbsp;&nbsp;<span class="datatypes" style="border-width: initial; border-color: initial; color: #2e8b57; font-weight: bold; ">int</span><span style="border-width: initial; border-color: initial; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ID;&nbsp;&nbsp;</span></span></li><li class="" style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">&nbsp;&nbsp;&nbsp;&nbsp;std::string&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Key;&nbsp;&nbsp;</span></li><li class="alt" style="border-width: initial; border-color: initial; line-height: 18px; "><span style="border-width: initial; border-color: initial; ">};&nbsp;&nbsp;</span></li></ol></div>&nbsp;<p>&nbsp;</p><p>通过 MemberType&lt; decltype( &amp;Call::ID ) &gt;::member_type 就可以获得是变量 ID 的类型（int）了。</p><p>注：如果你的编译器不支持 decltype, 可以使用 boost 库里的&nbsp;BOOST_TYPEOF 代替。</p><br />转自：<a href="http://blog.csdn.net/jadedrip/article/details/5583300">http://blog.csdn.net/jadedrip/article/details/5583300</a><img src ="http://www.cppblog.com/flyinghare/aggbug/152438.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2011-08-04 13:55 <a href="http://www.cppblog.com/flyinghare/archive/2011/08/04/152438.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++0x FAQ中文版</title><link>http://www.cppblog.com/flyinghare/archive/2011/06/23/149226.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Thu, 23 Jun 2011 00:30:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2011/06/23/149226.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/149226.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2011/06/23/149226.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/149226.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/149226.html</trackback:ping><description><![CDATA[<span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; border-collapse: separate; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="Apple-style-span"><span style="text-align: left; line-height: 21px; font-family: Arial, Helvetica, sans-serif; font-size: 12px" class="Apple-style-span"> 
<p style="line-height: 1.8em !important; margin: 10px 0px; word-break: break-all">译者前言：</p>
<p style="line-height: 1.8em !important; margin: 10px 0px; word-break: break-all">很快很快，最新的ISO C++标准C++0x就要来到我们身边了。</p>
<p style="line-height: 1.8em !important; margin: 10px 0px; word-break: break-all">今天获得<span style="line-height: normal !important; font-size: large; word-break: break-all"><a style="line-height: normal !important; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/" target="_blank">Stroustrup</a></span>先生的许可，开始翻译由他撰写和维护的<a style="line-height: normal !important; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" title="C++0x FAQ" href="http://www2.research.att.com/~bs/C++0xFAQ.html" target="_blank">C++0x FAQ</a>。我觉得这是一件伟大而光荣的事情，但是我又觉得压力很大，因为我的英语水平很差劲，同时自己的C++水平也很有限，很害怕在翻译过程中出现什么错误，贻笑大方不要紧，而误人子弟就罪过大了。所以，我这里的翻译只能算是抛砖引玉，如果你的英文很好，你可以直接阅读<a style="line-height: normal !important; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html" target="_blank">他的原文</a>。或者，你也可以参照两者进行阅读，我想一定会有更多的收获。</p>
<p style="line-height: 1.8em !important; margin: 10px 0px; word-break: break-all">当然，我也非常欢迎大家指出翻译中的错误，或者是加入进来和我一起翻译这份文档，共同为C++0x在<a style="line-height: normal !important; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" onclick="javascript:tagshow(event, '%D6%D0%B9%FA');" href="javascript:;" target="_self"><u style="line-height: normal !important; word-break: break-all"><strong style="line-height: normal !important; word-break: break-all">中国</strong></u></a>的推广做一点事情。你可以通过chenlq at live.com联系到我。</p>
<p style="line-height: 1.8em !important; margin: 10px 0px; word-break: break-all">对自己的翻译做一点说明：</p>
<ul style="padding-bottom: 0px; line-height: normal; margin: 0px 0px 0px 3em; padding-left: 0px; padding-right: 0px; word-break: break-all; padding-top: 0px"><li style="line-height: normal; word-break: break-all">在翻译的过程中，尽量遵照原文含义，可能有时候也会自己根据自己的理解加一点批注，希望可以帮助大家理解。</li><li style="line-height: normal; word-break: break-all">另外，虽然C++0x标准还没有正式公布，但是现在已经有很多编译器支持C++0x，比如gcc以及它在Windows下的MinGW，Visual C++ 2010也部分支持，大家可以使用这三款编译器尝试这个文档中的例子。</li><li style="line-height: normal; word-break: break-all">在下面的目录中，已经翻译的问题链接到相应的中文文档，未翻译的问题则链接到英文原文。</li></ul>
<p style="line-height: 1.8em !important; margin: 10px 0px; word-break: break-all">感谢所有参与翻译的志愿者：interma，Chilli，张潇，dabaidu，Yibo Zhu，lianggang jiang，nivo，陈良乔</p>
<p style="line-height: 1.8em !important; margin: 10px 0px; word-break: break-all">最后，祝大家阅读愉快:)</p>
<p style="line-height: 1.8em !important; margin: 10px 0px; word-break: break-all">---------------------------------------------------------------------------</p>
<p style="line-height: 1.8em !important; margin: 10px 0px; word-break: break-all"><span style="line-height: normal !important; font-size: 24px; word-break: break-all"><strong style="line-height: normal !important; word-break: break-all">目录</strong></span></p>
<ul style="padding-bottom: 0px; line-height: normal; margin: 0px 0px 0px 3em; padding-left: 0px; padding-right: 0px; word-break: break-all; padding-top: 0px"><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106281384.html">Stroustrup先生关于中文版的授权许可邮件</a></li></ul>
<ul style="padding-bottom: 0px; line-height: normal; margin: 0px 0px 0px 3em; padding-left: 0px; padding-right: 0px; word-break: break-all; padding-top: 0px"><li style="line-height: normal; word-break: break-all">
<div style="text-align: left; line-height: 1.8em !important; margin: 10px 0px; word-break: break-all"><a style="background-image: none; line-height: normal !important; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106188986.html" target="_blank">Stroustrup先生关于C++0x FAQ的一些说明</a></div></li></ul>
<p style="line-height: 1.8em !important; margin: 10px 0px; word-break: break-all"><span style="line-height: normal !important; font-size: 18px; word-break: break-all"><strong style="line-height: normal !important; word-break: break-all">关于C++0x的一般性的问题：</strong></span></p>
<ul style="padding-bottom: 0px; line-height: normal; margin: 0px 0px 0px 3em; padding-left: 0px; padding-right: 0px; word-break: break-all; padding-top: 0px"><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106199527.html">您是如何看待C++0x的?</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107114133.html">什么时候C++0x会成为一部正式的标准呢？</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107118019.html">编译器何时将会实现C++0x标准呢？<br style="line-height: normal; word-break: break-all" /></a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107273163.html">我们何时可以用到新的标准库文件？</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107275263.html">C++0x将提供何种新的语言特性呢？</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107573899.html">C++0x会提供哪些新的标准库文件呢？</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107576996.html">C++0x努力要达到的目标有哪些？</a></li></ul>
<p style="line-height: 1.8em !important; margin: 10px 0px; word-break: break-all"></p>
<p style="line-height: 1.8em !important; margin: 10px 0px; word-break: break-all"></p>
<ul style="padding-bottom: 0px; line-height: normal; margin: 0px 0px 0px 3em; padding-left: 0px; padding-right: 0px; word-break: break-all; padding-top: 0px"><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html#specific-aims">What specific design aims guided the committee?</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html#WG21">Where can I find the committee papers?</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107675380.html">从哪里可以获得有关C++0x的学术性和</a><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" onclick="javascript:tagshow(event, '%BC%BC%CA%F5');" href="javascript:;" target="_self"><u style="line-height: normal; word-break: break-all"><strong style="line-height: normal; word-break: break-all">技术</strong></u></a>性的参考资料？</li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107680325.html">还有哪些地方我可以读到关于C++0x的资料？</a>&nbsp;</li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107676913.html">有关于C++0x的视频吗？</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107680910.html">C++0x难学吗?</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107678844.html">标准委员会是如何运行的？</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107679938.html">谁在标准委员会里？</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107681574.html">实现者应以什么顺序提供C++0x特性？</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107682088.html">将会是C++1x吗？</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107689911.html">标准中的"concepts"怎么了?</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107682597.html">有你不喜欢的C++特性吗？</a></li></ul>
<p style="line-height: 1.8em !important; margin: 10px 0px; word-break: break-all"></p>
<p style="line-height: 1.8em !important; margin: 10px 0px; word-break: break-all"><span style="line-height: normal !important; font-size: 18px; word-break: break-all"><strong style="line-height: normal !important; word-break: break-all"></strong></span></p>
<p style="line-height: 1.8em !important; margin: 10px 0px; word-break: break-all"><span style="line-height: normal !important; font-size: 18px; word-break: break-all"><strong style="line-height: normal !important; word-break: break-all">关于独立的语言特性的问题</strong></span><span style="line-height: normal !important; font-size: 18px; word-break: break-all"><strong style="line-height: normal !important; word-break: break-all">:</strong></span></p>
<ul style="padding-bottom: 0px; line-height: normal; margin: 0px 0px 0px 3em; padding-left: 0px; padding-right: 0px; word-break: break-all; padding-top: 0px"><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106408881.html">__cplusplus<br style="line-height: normal; word-break: break-all" /></a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html#align">alignments</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106288350.html">attributes(属性)</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html#std-atomics">atomic operations</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106418093.html">auto</a>(<a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106418093.html">从初始化中推断数据类型</a>)</li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106439814.html">C99功能特性</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106441102.html">enum class</a>(<a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106441102.html">枚举类&#8212;&#8212;具有类域和强类型的枚举</a>)</li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106560375.html">复制和重新抛出异常</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106842754.html">常量表达式（constexpr）</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106584747.html">decltype &#8211; 推断表达式的数据类型</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107294018.html">默认或者禁用函数&#8212;控制默认函数</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106705361.html">委托构造函数（Delegating constructors）</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106957923.html">并发性动态初始化和析构</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106958304.html">显式转换操作符</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107127745.html">扩展整型</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107128945.html">外部模板声明</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107126716.html">序列for循环语句</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107124982.html">返回类型后置语法</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107272834.html">类内部成员的初始化</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html#inheriting">继承的构造函数（inherited constructors）</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106837601.html">初始化列表</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106857469.html">Lambdas</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106957510.html">用作模板参数的局部类型</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106961761.html">long long（长长整数类型）</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106963060.html">内存模型</a></li><li style="line-height: normal; word-break: break-all">move语义（参见<a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107446664.html">右值引用</a>）</li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html#inline-namespace">内联命名空间（Inline namespace）</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106835685.html">预防窄转换</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107147212.html">nullptr&#8212;&#8212;空指针标识</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107146252.html">PODs</a></li><li style="line-height: normal; word-break: break-all">range for statement(参见<a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107126716.html">序列for循环语句</a>)</li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107580560.html">原生字符串标识</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107581140.html">右角括号</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107446664.html">右值引用</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html#SFINAE">Simple SFINAE rule</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107591653.html">静态（编译期）断言 -- static_assert</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107592264.html">模板别名（正式的名称为"template typedef"）</a></li><li style="line-height: normal; word-break: break-all">template typedef(参见<a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107592264.html">模板别名</a>)</li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107593175.html">线程本地化存储 (thread_local)</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107594678.html">unicode字符</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html#uniform-init">Uniform. initialization syntax and semantics</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html#unions">unions</a>(generalized)</li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106729870.html">用户定义数据标识（User-defined literals）</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106751779.html">可变参数模板（Variadic Templates）</a></li></ul>
<p style="line-height: 1.8em !important; margin: 10px 0px; word-break: break-all">我经常从提案中借用一些例子。所以，我要感谢这些提案的作者们。另外，我也从自己的访谈和论文中借用了很多例子。</p>
<p style="line-height: 1.8em !important; margin: 10px 0px; word-break: break-all"><span style="line-height: normal !important; font-size: 18px; word-break: break-all"><strong style="line-height: normal !important; word-break: break-all">关于标准库的问题：</strong></span></p>
<ul style="padding-bottom: 0px; line-height: normal; margin: 0px 0px 0px 3em; padding-left: 0px; padding-right: 0px; word-break: break-all; padding-top: 0px"><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106969647.html">abandoning_a_process</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106967152.html">算法方面的改进</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106968957.html">array</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106964525.html">async()</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106969189.html">atomic_operations</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html#std-condition">Condition variables</a></li><li style="line-height: normal; word-break: break-all">Improvements to<a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html#containers">containers</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107468086.html">std::function 和 std::bind</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html#std-forward_list">forward_list</a>a singly-liked list</li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html#std-future">future and promise</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107119946.html">垃圾回收（应用程序二进制接口）</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106956407.html">无序容器（Unordered containers）</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107122138.html">metaprogramming and type traits</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/107121484.html">互斥</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html#std-random">random number generators</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html#std-regex">regex</a>a regular expression library</li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html#scoped-allocator">scoped allocators</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html#std-shared_ptr">shared_ptr</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html#std-unique_ptr">smart pointers</a>; see shared_ptr, weak_ptr, and unique_ptr</li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html#std-thread">threads</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html#std-duration">Time utilities</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106960521.html">标准库中的元组（std::tuple）</a>-</li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106956757.html">unique_ptr</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106956407.html">无序容器（Unordered containers）</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://imcc.blogbus.com/logs/106705971.html">weak_ptr</a></li><li style="line-height: normal; word-break: break-all"><a style="background-image: none; line-height: normal; padding-left: 0px; color: rgb(51,51,51); word-break: break-all; text-decoration: underline" href="http://www2.research.att.com/~bs/C++0xFAQ.html#system-error">system error</a></li></ul></span></span><br class="Apple-interchange-newline" />转自：<a href="http://imcc.blogbus.com/logs/106046323.html">http://imcc.blogbus.com/logs/106046323.html</a><img src ="http://www.cppblog.com/flyinghare/aggbug/149226.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2011-06-23 08:30 <a href="http://www.cppblog.com/flyinghare/archive/2011/06/23/149226.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【C++0x】表达式之类型（decltype）</title><link>http://www.cppblog.com/flyinghare/archive/2011/06/23/149225.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Thu, 23 Jun 2011 00:25:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2011/06/23/149225.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/149225.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2011/06/23/149225.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/149225.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/149225.html</trackback:ping><description><![CDATA[<span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; border-collapse: separate; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="Apple-style-span"><span style="border-collapse: collapse; font-family: song, Verdana; font-size: 12px" class="Apple-style-span">C++0x引入了新的关键字decltype，它是一个操作符，用来取得表达式的类型，主要在泛型编程中使用。这里，简单介绍一下语法规则。<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />语法形式：decltype (<span style="font-style: italic">expression</span>)<br style="font: 12px song, Verdana" />其中，这里的括号必不可少（这点不同于sizeof操作符）。decltype(e)可看到是一个类型别名，并且<span style="color: rgb(255,1,2)">不会对表达式e进行计算</span>（即只有编译时行为而无运行时行为）。另外，不允许把decltype作用于一个类型，因为没有任何理由要这样做。<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" /><span style="color: rgb(0,1,255)">确定decltype(e)类型的规则如下</span>：<br style="font: 12px song, Verdana" /><span style="color: rgb(255,1,2)">Rule-1</span>. 如果e是一个标识符表达式或者类成员访问表达式，那么decltype(e)就是e所命名的实体的类型。如果没有此实体或者e命名了一个重载函数集，那么程序是ill-formed的。<br style="font: 12px song, Verdana" /><span style="color: rgb(255,1,2)">Rule-2</span>. 如果e是一个函数调用或者一个重载操作符调用（忽略e外面的括号），那么decltype(e)就是该函数的返回类型。<br style="font: 12px song, Verdana" /><span style="color: rgb(255,1,2)">Rule-3</span>. 否则，假设e的类型是T：如果e是一个左值，则decltype(e)就是T&amp;；否则（e是一个右值），decltype(e)就是T。<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />举例分析如下（内容来自参考Ref1）：<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" /><span style="color: rgb(0,1,255)">eg1 名字空间或局部作用域内的变量</span>（Rule-1）<br style="font: 12px song, Verdana" />int a;<br style="font: 12px song, Verdana" />int&amp; b = a;<br style="font: 12px song, Verdana" />const int&amp; c = a;<br style="font: 12px song, Verdana" />const int d = 5;<br style="font: 12px song, Verdana" />const A e;<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />（注：不能直接编译，这里写出来只是分析）<br style="font: 12px song, Verdana" />decltype(a) // int<span class="Apple-converted-space">&nbsp;</span><br style="font: 12px song, Verdana" />decltype(b) // int&amp;<br style="font: 12px song, Verdana" />decltype(c) // const int&amp;<br style="font: 12px song, Verdana" />decltype(d) // const int<br style="font: 12px song, Verdana" />decltype(e) // const A<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />但需要注意<span style="color: rgb(255,1,2)">括号可能会影响结果</span>，例如：<br style="font: 12px song, Verdana" />decltype((a));&nbsp; // int&amp; （此时(a)表达式不满足Rule-1和Rule-2，应用Rule-3，而表达式(a)是一个左值，所以为int&amp;）<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" /><span style="color: rgb(0,1,255)">eg2 函数形参</span>（Rule-1）<br style="font: 12px song, Verdana" />void foo(int a, int&amp; b, float&amp;&amp; c, int* d)<br style="font: 12px song, Verdana" />{<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; decltype(a) // int<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; decltype(b) // int&amp;<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; decltype(c) // float&amp;&amp;<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; decltype(d) // int*<br style="font: 12px song, Verdana" />}<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" /><span style="color: rgb(0,1,255)">eg3 函数类型</span>（Rule-1）<br style="font: 12px song, Verdana" />int foo(char);<br style="font: 12px song, Verdana" />int bar(char);<br style="font: 12px song, Verdana" />int bar(int);<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />decltype(foo) // int(char)<br style="font: 12px song, Verdana" />decltype(bar) // error, bar is overloaded<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />但需要注意当<span style="color: rgb(255,1,2)">形成函数指针</span>时适用Rule-3：<br style="font: 12px song, Verdana" />decltype(&amp;foo) // int(*)(char)<br style="font: 12px song, Verdana" />decltype(*&amp;foo) // int(&amp;)(char)<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" /><span style="color: rgb(0,1,255)">eg4 数据类型</span>（Rule-1）<br style="font: 12px song, Verdana" />int a[10];<br style="font: 12px song, Verdana" />decltype(a)&nbsp; // int[10]<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" /><span style="color: rgb(0,1,255)">eg5 成员变量</span>（Rule-1）<br style="font: 12px song, Verdana" />class A {<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; int a;<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; int&amp; b;<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; static int c;<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp;<span class="Apple-converted-space">&nbsp;</span><br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; void foo() {<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; decltype(a)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // int<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; decltype(this-&gt;a)&nbsp;&nbsp;&nbsp; // int<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; decltype((*this).a)&nbsp; // int<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; decltype(b)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // int&amp;<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; decltype(c)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // int (static members are treated as variables in namespace scope)<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; }<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; void bar() const {<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; decltype(a)&nbsp;&nbsp; // int<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; decltype(b)&nbsp;&nbsp; // int&amp;<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; decltype(c)&nbsp;&nbsp; // int<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; }<br style="font: 12px song, Verdana" />};<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />A aa;<br style="font: 12px song, Verdana" />const A&amp; caa = aa;<br style="font: 12px song, Verdana" />decltype(aa.a)&nbsp; // int<br style="font: 12px song, Verdana" />decltype(aa.b)&nbsp;&nbsp; // int&amp;<br style="font: 12px song, Verdana" />decltype(caa.a)&nbsp; // int<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />但<span style="color: rgb(255,1,2)">内置操作符.*和-&gt;*<span style="color: rgb(0,1,2)">适用Rule-3</span></span>：<br style="font: 12px song, Verdana" />decltype(aa.*&amp;A::a) // int&amp;<br style="font: 12px song, Verdana" />decltype(aa.*&amp;A::b) // illegal, cannot take the address of a reference member<br style="font: 12px song, Verdana" />decltype(caa.*&amp;A::a) // const int&amp;<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" /><span style="color: rgb(0,1,255)">eg6 this</span>（Rule-3）<br style="font: 12px song, Verdana" />class X {<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; void foo() {<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; decltype(this)&nbsp;&nbsp;&nbsp; // X*，因为this是右值<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; decltype(*this)&nbsp;&nbsp; // X&amp;，因为*this是左值<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; }<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; void bar()<span class="Apple-converted-space">&nbsp;</span><span style="color: rgb(255,1,2)">const<span class="Apple-converted-space">&nbsp;</span></span>{<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; decltype(this)&nbsp;&nbsp; //<span class="Apple-converted-space">&nbsp;</span><span style="color: rgb(255,1,2)">const<span class="Apple-converted-space">&nbsp;</span></span>X*<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; decltype(*this)&nbsp; // const X&amp;<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; }<br style="font: 12px song, Verdana" />};<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" /><span style="color: rgb(0,1,255)">eg7 指向成员变量和成员函数的指针</span>（Rule-1）<br style="font: 12px song, Verdana" />class A {<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; int x;<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; int&amp; y;<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; int foo(char);<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; int&amp; bar() const;<br style="font: 12px song, Verdana" />};<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />decltype(&amp;A::x) &nbsp;&nbsp; // int A::*<br style="font: 12px song, Verdana" />decltype(&amp;A::y)&nbsp;&nbsp;&nbsp; // error: pointers to reference members are disallowed (8.3.3 (3))<br style="font: 12px song, Verdana" />decltype(&amp;A::foo) // int (A::*) (char)<br style="font: 12px song, Verdana" />decltype(&amp;A::bar) // int&amp; (A::*) () const<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" /><span style="color: rgb(0,1,255)">eg8 字面值</span>（Rule-3）<br style="font: 12px song, Verdana" />（字符串字面值是左值，其它字面值都是右值）<br style="font: 12px song, Verdana" />decltype("decltype") // const char(&amp;)[9]<br style="font: 12px song, Verdana" />decltype(1) // int<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" /><span style="color: rgb(0,1,255)">eg9 冗余的引用符（&amp;）和CV修饰符</span><br style="font: 12px song, Verdana" />由于decltype表达式是一个类型别名，因此冗余的引用符（&amp;）和CV修饰符被忽略：<br style="font: 12px song, Verdana" />int&amp; i = ...;<br style="font: 12px song, Verdana" />const int j = ...;<br style="font: 12px song, Verdana" />decltype(i)&amp; &nbsp; &nbsp; &nbsp; &nbsp; // int&amp;. The redundant &amp; is ok<br style="font: 12px song, Verdana" />const decltype(j)&nbsp;&nbsp; // const int. The redundant const is ok<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" /><span style="color: rgb(0,1,255)">eg10 函数调用</span>（Rule-2）<br style="font: 12px song, Verdana" />int foo();<br style="font: 12px song, Verdana" />decltype(foo())&nbsp;&nbsp;&nbsp; // int<br style="font: 12px song, Verdana" />float&amp; bar(int);<br style="font: 12px song, Verdana" />decltype (bar(1))&nbsp; // float&amp;<br style="font: 12px song, Verdana" />class A { ... };<br style="font: 12px song, Verdana" />const A bar();<br style="font: 12px song, Verdana" />decltype (bar())&nbsp;&nbsp;&nbsp; // const A<br style="font: 12px song, Verdana" />const A&amp; bar2();<br style="font: 12px song, Verdana" />decltype (bar2())&nbsp; // const A&amp;<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" /><span style="color: rgb(0,1,255)">eg11 内置操作符</span>（Rule-3）<br style="font: 12px song, Verdana" />decltype(1+2) &nbsp; &nbsp; // int (+ returns an rvalue)<br style="font: 12px song, Verdana" />int* p;<br style="font: 12px song, Verdana" />decltype(*p)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // int&amp; (* returns an lvalue)<br style="font: 12px song, Verdana" />int a[10];<br style="font: 12px song, Verdana" />decltype(a[3]); &nbsp; &nbsp; // int&amp; ([] returns an lvalue)<br style="font: 12px song, Verdana" />int i; int&amp; j = i;<br style="font: 12px song, Verdana" />decltype (i = 5)&nbsp;&nbsp; // int&amp;, because assignment to int returns an lvalue<br style="font: 12px song, Verdana" />decltype (j = 5)&nbsp;&nbsp; // int&amp;, because assignment to int returns an lvalue<br style="font: 12px song, Verdana" />decltype (++i);&nbsp;&nbsp;&nbsp; // int&amp;<br style="font: 12px song, Verdana" />decltype (i++); &nbsp;&nbsp; // int (rvalue)<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />如何用程序验证decltype的结果？可以参考下面的程序对上面的分析结果进行验证：<br style="font: 12px song, Verdana" />F:\tmp&gt;type decltype_eg1.cpp<br style="font: 12px song, Verdana" />#include &lt;iostream&gt;<br style="font: 12px song, Verdana" />#include &lt;string&gt;<br style="font: 12px song, Verdana" />using namespace std;<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />template &lt;typename T&gt;<br style="font: 12px song, Verdana" />string Foo()<br style="font: 12px song, Verdana" />{<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; return "unknown";<br style="font: 12px song, Verdana" />}<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />template &lt;&gt;<br style="font: 12px song, Verdana" />string Foo&lt;int&gt;()<br style="font: 12px song, Verdana" />{<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; return "int";<br style="font: 12px song, Verdana" />}<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />template &lt;&gt;<br style="font: 12px song, Verdana" />string Foo&lt;const int&gt;()<br style="font: 12px song, Verdana" />{<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; return "const int";<br style="font: 12px song, Verdana" />}<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />template &lt;&gt;<br style="font: 12px song, Verdana" />string Foo&lt;int &amp;&gt;()<br style="font: 12px song, Verdana" />{<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; return "int&amp;";<br style="font: 12px song, Verdana" />}<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />template &lt;&gt;<br style="font: 12px song, Verdana" />string Foo&lt;const int&amp;&gt;()<br style="font: 12px song, Verdana" />{<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; return "const int&amp;";<br style="font: 12px song, Verdana" />}<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />class A{};<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />template &lt;&gt;<br style="font: 12px song, Verdana" />string Foo&lt;A&gt;()<br style="font: 12px song, Verdana" />{<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; return "A";<br style="font: 12px song, Verdana" />}<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />int main()<br style="font: 12px song, Verdana" />{<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; int a;<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; int &amp;b = a;<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; const int &amp;c = a;<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; const int d = 5;<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; A e;<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; double f;<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; cout &lt;&lt; "a: " &lt;&lt; Foo&lt;decltype(a)&gt;() &lt;&lt; endl;<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; cout &lt;&lt; "b: " &lt;&lt; Foo&lt;decltype(b)&gt;() &lt;&lt; endl;<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; cout &lt;&lt; "c: " &lt;&lt; Foo&lt;decltype(c)&gt;() &lt;&lt; endl;<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; cout &lt;&lt; "d: " &lt;&lt; Foo&lt;decltype(d)&gt;() &lt;&lt; endl;<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; cout &lt;&lt; "e: " &lt;&lt; Foo&lt;decltype(e)&gt;() &lt;&lt; endl;<br style="font: 12px song, Verdana" />&nbsp;&nbsp;&nbsp; cout &lt;&lt; "f: " &lt;&lt; Foo&lt;decltype(f)&gt;() &lt;&lt; endl;<br style="font: 12px song, Verdana" />}<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />F:\tmp&gt;g++ decltype_eg1.cpp -std=c++0x<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />F:\tmp&gt;a.exe<br style="font: 12px song, Verdana" />a: int<br style="font: 12px song, Verdana" />b: int&amp;<br style="font: 12px song, Verdana" />c: const int&amp;<br style="font: 12px song, Verdana" />d: const int<br style="font: 12px song, Verdana" />e: A<br style="font: 12px song, Verdana" />f: unknown<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />F:\tmp&gt;gcc --version<br style="font: 12px song, Verdana" />gcc (GCC) 4.3.0 20080305 (alpha-testing) mingw-20080502<br style="font: 12px song, Verdana" />Copyright (C) 2008 Free Software Foundation, Inc.<br style="font: 12px song, Verdana" />This is free software; see the source for copying conditions.&nbsp; There is NO<br style="font: 12px song, Verdana" />warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.<br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" /><br style="font: 12px song, Verdana" />参考资料：<br style="font: 12px song, Verdana" />Ref1:<span class="Apple-converted-space">&nbsp;</span><a style="color: rgb(0,68,182); text-decoration: underline" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2115.pdf" target="_blank">Decltype (revision 6): proposed wording</a><br style="font: 12px song, Verdana" />Ref2:<span class="Apple-converted-space">&nbsp;</span><a style="color: rgb(0,68,182); text-decoration: underline" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2343.pdf" target="_blank">Decltype (revision 7): proposed wording</a></span></span><br /><br />转自：<a href="http://www.cublog.cn/u/18517/showart_1664016.html">http://www.cublog.cn/u/18517/showart_1664016.html</a><img src ="http://www.cppblog.com/flyinghare/aggbug/149225.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2011-06-23 08:25 <a href="http://www.cppblog.com/flyinghare/archive/2011/06/23/149225.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C/C++的数值常数后缀的使用总结</title><link>http://www.cppblog.com/flyinghare/archive/2011/06/16/148764.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Thu, 16 Jun 2011 02:54:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2011/06/16/148764.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/148764.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2011/06/16/148764.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/148764.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/148764.html</trackback:ping><description><![CDATA[<span style="font-family: Verdana, Arial, Tahoma; "><div style="padding-top: 8px; padding-right: 16px; padding-bottom: 8px; padding-left: 16px; margin-top: 8px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; line-height: 25px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafdfe; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #dddddd; border-right-color: #dddddd; border-bottom-color: #dddddd; border-left-color: #dddddd; font-size: 14px; color: #555555; background-position: initial initial; background-repeat: initial initial; ">1.数值常数有：整型常数、浮点常数；<br style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; " />2.只有数值常数才有后缀说明；<br style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; " />3.数值常数后缀不区分字母大小写。</div><div style="padding-top: 12px; padding-right: 16px; padding-bottom: 12px; padding-left: 16px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-size: 14px; line-height: 25px; color: #333333; "><table width="100%" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><tbody style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><tr style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><td style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><div id="art" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 15px; margin-right: 15px; margin-bottom: 15px; margin-left: 15px; "><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">1.数值常数有：整型常数、浮点常数；<br style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; " />2.只有数值常数才有后缀说明；<br style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; " />3.数值常数后缀不区分字母大小写。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">(1)整型常数的表示形式有：十进制形式、以0开头的八进制形式、以0x开头的十六进制形式，无二进制形式。<br style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; " />&nbsp;&nbsp; 整型常数默认是signed int的。<br style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; " />&nbsp;&nbsp; 对整型常数进行类型转换的后缀只有：u或U(unsigned)、l或L(long)、u/U与l/L的组合(如：ul、lu、Lu等)。例：100u;&nbsp; -123u;&nbsp; 0x123l;</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">(2)浮点常数的表示形式有：科学计数形式和小数点形式。<br style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; " />&nbsp;&nbsp; 浮点常数默认是double的。<br style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; " />&nbsp;&nbsp; 对浮点常数进行类型转换的后缀只有：f或F（单精度浮点数）、l或L（长双精度浮点数）。(注：因浮点型常数总是有符号的，故没有u或U后缀)。例：1.23e5f;&nbsp; 1.23l;&nbsp; -123.45f;</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">至于具体的应用，自己留意吧！</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br /></p></div></td></tr></tbody></table></div></span><span style="font-family: Verdana, Arial, Tahoma; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-size: medium; ">转自：<a href="http://edu.codepub.com/2010/1017/26462.php">http://edu.codepub.com/2010/1017/26462.php</a></span><span style="font-family: Verdana, Arial, Tahoma; "><div style="padding-top: 12px; padding-right: 16px; padding-bottom: 12px; padding-left: 16px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font class="Apple-style-span" size="3"><span class="Apple-style-span" style="line-height: normal; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"><br /></span></font></div></span><img src ="http://www.cppblog.com/flyinghare/aggbug/148764.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2011-06-16 10:54 <a href="http://www.cppblog.com/flyinghare/archive/2011/06/16/148764.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++0x新特性：委托构造函数（delegate constructor）</title><link>http://www.cppblog.com/flyinghare/archive/2011/05/27/147332.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Fri, 27 May 2011 01:16:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2011/05/27/147332.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/147332.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2011/05/27/147332.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/147332.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/147332.html</trackback:ping><description><![CDATA[<span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; border-collapse: separate; font: medium Simsun; white-space: normal; orphans: 2; color: #000000; word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="Apple-style-span"><span style="text-align: left; line-height: 23px; font-family: Verdana, Arial, Helvetica, sans-serif; color: #71716f; font-size: 14px" class="Apple-style-span"> 
<p style="padding-bottom: 0px; margin: 0px 0px 1em; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="color: #ff0000; font-size: 24pt; ">（注意：经测试，VS2010 不支持该特性）<br /></span><br />C++0x带来的委托构造函数（delegate constructor），说白了，其实就是在某一个构造函数中调用另外一个构造函数，实际上，类似的特性在Java中早已经存在了，好像就是在构造函数之后跟上Base()来实现的。</p>
<p style="padding-bottom: 0px; margin: 0px 0px 1em; padding-left: 0px; padding-right: 0px; padding-top: 0px">委托构造函数确实能够带来一些便利，常常，我们需要在两个相类似的构造函数中实现相同的功能，在以往，我们也许会通过将这些相同的功能集中到一个init()中来实现，两个构造函数调用同一个函数。现在C++0x有了委托构造函数，我们可以将这些相同的功能在某个基础的构造函数中实现，另外一个构造函数调用这个基础构造函数就可以了。一个简单的例子是：</p>
<p style="padding-bottom: 0px; margin: 0px 0px 1em; padding-left: 0px; padding-right: 0px; padding-top: 0px">#include &lt;iostream&gt;<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />using namespace std;<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />// 正数类<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />class PositiveNumber<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />{<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />public:<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />// 带参数的构造函数，附带了对参数进行检查的功能&nbsp;<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />PositiveNumber(int x)<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;{<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;if( x &lt; 0)<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;&nbsp;throw "必须为正数";<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;&nbsp;_x = x;<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;}<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />// 不带参数的默认构造函数，以1为参数委托调用带参数的构造函数<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />PositiveNumber(): Positive{1}<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;{}</p>
<p style="padding-bottom: 0px; margin: 0px 0px 1em; padding-left: 0px; padding-right: 0px; padding-top: 0px">private:<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;int _x;<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />};</p>
<p style="padding-bottom: 0px; margin: 0px 0px 1em; padding-left: 0px; padding-right: 0px; padding-top: 0px">int main(int argc, char *argv[])<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />{<span class="Apple-converted-space">&nbsp;</span><br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;PositiveNumber one;<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;PositiveNumber two(2);<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />&nbsp;return 0;<br style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px" />}</p>
<p style="padding-bottom: 0px; margin: 0px 0px 1em; padding-left: 0px; padding-right: 0px; padding-top: 0px">委托构造函数，省去了为了实现共同功能需要另外的intit()函数，为编码带来了便利。</p></span></span><br /><br />转自：<a href="http://blog.csdn.net/shellching/archive/2010/04/20/5506019.aspx">http://blog.csdn.net/shellching/archive/2010/04/20/5506019.aspx</a><img src ="http://www.cppblog.com/flyinghare/aggbug/147332.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2011-05-27 09:16 <a href="http://www.cppblog.com/flyinghare/archive/2011/05/27/147332.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ 新特性-右值引用</title><link>http://www.cppblog.com/flyinghare/archive/2011/05/27/147331.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Fri, 27 May 2011 01:15:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2011/05/27/147331.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/147331.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2011/05/27/147331.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/147331.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/147331.html</trackback:ping><description><![CDATA[<span style="widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; border-collapse: separate; font: medium Simsun; white-space: normal; orphans: 2; color: rgb(0,0,0); word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="Apple-style-span"><span style="text-align: left; line-height: 21px; font-family: verdana, sans-serif; font-size: 14px" class="Apple-style-span"> 
<p style="padding-bottom: 0px; margin: 1em 0px 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px">作为最重要的一项语言特性，右值引用(rvalue references)被引入到 C++0x中。我们可以通过操作符&#8220;&amp;&amp;&#8221;来声明一个右值引用，原先在C++中使用&#8220;&amp;&#8221;操作符声明的引用现在被称为左值引用。&nbsp;</p>
<div style="border-bottom: windowtext 0.5pt solid; border-left: windowtext 0.5pt solid; padding-bottom: 4px; background-color: rgb(230,230,230); padding-left: 5.4pt; width: 895px; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; border-right: windowtext 0.5pt solid; padding-top: 4px; background-origin: initial; background-clip: initial">
<div><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>a;<br /></span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&amp;</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>a_lvref<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>a;&nbsp;&nbsp;</span><span style="color: rgb(0,0,0)">//</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>左值引用<br /><br /></span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>b;<br /></span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&amp;&amp;</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>b_rvref<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>b;&nbsp;&nbsp;</span><span style="color: rgb(0,0,0)">//</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>右值应用</span></div></div>
<p style="padding-bottom: 0px; margin: 1em 0px 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp; 左值引用和右值引用的表现行为基本一致，它们唯一的差别就是右值引用可以绑定到一个临时对象(右值)上，而左值引用不可以。例如：&nbsp;</p>
<div style="border-bottom: windowtext 0.5pt solid; border-left: windowtext 0.5pt solid; padding-bottom: 4px; background-color: rgb(230,230,230); padding-left: 5.4pt; width: 895px; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; border-right: windowtext 0.5pt solid; padding-top: 4px; background-origin: initial; background-clip: initial">
<div><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&amp;</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>a_lvref<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,0)">//</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0,0,255)">error</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>C2440:<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0,128,0)">'</span><span style="color: rgb(0,128,0)">initializing' : cannot convert from 'int' to 'int &amp;'&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)"><br /></span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">&amp;&amp;</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>b_rvref<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)">();&nbsp;&nbsp;</span><span style="color: rgb(0,0,0)">//</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>OK!</span></div></div>
<p style="padding-bottom: 0px; margin: 1em 0px 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp; 在第一行代码中，我们将一个临时对象int()绑定到一个左值引用，将产生一个编译错误。而在第二行中，我们将临时对象绑定到右值引用，就可以顺利通过编译。<br /><br />&nbsp; 右值是无名的数据，例如函数的返回值一般说来就是右值。当对右值进行操作的时候，右值本身往往没有必要保留，因此在某些情况下可以直接&#8220;移动&#8221;之。通过右值引用，程序可以明确的区分出传入的参数是否为右值，从而避免了不必要的拷贝，程序的效率也就得到了提高。我们考虑一个简单的数据交换的小程序，从中来体会右值引用所带来的效率提升。我们可以写一个函数swap来实现两个变量值的交换：</p>
<div style="border-bottom: windowtext 0.5pt solid; border-left: windowtext 0.5pt solid; padding-bottom: 4px; background-color: rgb(230,230,230); padding-left: 5.4pt; width: 895px; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; border-right: windowtext 0.5pt solid; padding-top: 4px; background-origin: initial; background-clip: initial">
<div><span style="color: rgb(0,0,0)">template<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0,0,0)">&lt;</span><span style="color: rgb(0,0,255)">class</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>T</span><span style="color: rgb(0,0,0)">&gt;</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>swap(T</span><span style="color: rgb(0,0,0)">&amp;</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>a, T</span><span style="color: rgb(0,0,0)">&amp;</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>b)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;T tmp(a);&nbsp;&nbsp;<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0,0,0)">//</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>tmp对象创建后，我们就拥有了a的两份拷贝<br />&nbsp;&nbsp;&nbsp;&nbsp;a<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>b;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,0)">//</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>现在我们拥有b的两份拷贝<br />&nbsp;&nbsp;&nbsp;&nbsp;b<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>tmp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,0)">//</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>现在我们拥有a的两份拷贝<br />}</span></div></div>
<p style="padding-bottom: 0px; margin: 1em 0px 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp; 在这段代码中，虽然我们只是为了进行简单的数据交换，但是却执行了多次对象拷贝。这些对象的拷贝操作，特别是当这些对象比较大的时候，无疑会影响程序的效率。<br /><br />&nbsp; 那么，如果使用右值引用如何实现呢？</p>
<div style="border-bottom: windowtext 0.5pt solid; border-left: windowtext 0.5pt solid; padding-bottom: 4px; background-color: rgb(230,230,230); padding-left: 5.4pt; width: 895px; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; border-right: windowtext 0.5pt solid; padding-top: 4px; background-origin: initial; background-clip: initial">
<div><span style="color: rgb(0,0,0)">//</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>RValueRef.cpp : Defines the entry point<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0,0,255)">for</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>the console application.<br /></span><span style="color: rgb(0,0,0)">//</span><span style="color: rgb(0,0,0)"><br /><br />#include<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(128,0,0)">"</span><span style="color: rgb(128,0,0)">stdafx.h</span><span style="color: rgb(128,0,0)">"</span><span style="color: rgb(0,0,0)"><br /><br />template<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0,0,0)">&lt;</span><span style="color: rgb(0,0,255)">class</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>T</span><span style="color: rgb(0,0,0)">&gt;</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span><br />T</span><span style="color: rgb(0,0,0)">&amp;&amp;</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>move(T</span><span style="color: rgb(0,0,0)">&amp;&amp;</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>a)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>a;<br />}<br /><br />template<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0,0,0)">&lt;</span><span style="color: rgb(0,0,255)">class</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>T</span><span style="color: rgb(0,0,0)">&gt;</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>void swap(T</span><span style="color: rgb(0,0,0)">&amp;</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>a, T</span><span style="color: rgb(0,0,0)">&amp;</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>b)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;T tmp(move(a));<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0,0,0)">//</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>对象a被移动到对象tmp，a被清空<br />&nbsp;&nbsp;&nbsp;&nbsp;a<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>move(b);&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,0)">//</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>对象b被移动到对象a，b被清空<br />&nbsp;&nbsp;&nbsp;&nbsp;b<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>move(tmp);&nbsp;&nbsp;</span><span style="color: rgb(0,0,0)">//</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>对象tmp被移动到对象b<br />}<br /><br /></span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>_tmain(</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>argc, _TCHAR</span><span style="color: rgb(0,0,0)">*</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>argv[])<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>a<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(128,0,128)">1</span><span style="color: rgb(0,0,0)">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">int</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span>b<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(128,0,128)">2</span><span style="color: rgb(0,0,0)">;<br />&nbsp;&nbsp;&nbsp;&nbsp;swap(a, b);<br /><br />&nbsp;&nbsp;<span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(0,0,255)">return</span><span style="color: rgb(0,0,0)"><span class="Apple-converted-space">&nbsp;</span></span><span style="color: rgb(128,0,128)">0</span><span style="color: rgb(0,0,0)">;<br />}</span></div></div>
<p style="padding-bottom: 0px; margin: 1em 0px 0.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp; 在这段重新实现的代码中，我们使用了一个move()函数来代替对象的赋值操作符&#8220;=&#8221;,move()只是简单地接受一个右值引用或者左值引用作为参数，然后直接返回相应对象的右值引用。这一过程不会产生拷贝(Copy)操作，而只会将源对象移动(Move)到目标对象。<br /><br />&nbsp; 正是拷贝(Copy)和移动(Move)的差别，使得右值引用成为C++0x中最激动人心的新特性之一。从实践角度讲，它能够完美是解决C++中长久以来为人所诟病的临时对象的效率问题。从语言本身讲，它健全了C++中的引用类型在左值右值方面的缺陷。从库设计者的角度讲，它给库设计者又带来了一把利器。而对于广大的库使用者而言，不动一兵一卒便能够获得&#8220;免费的&#8221;效率提升。</p></span></span><br /><br />摘自：<a href="http://blog.csdn.net/shellching/archive/2010/04/20/5506019.aspx">http://blog.csdn.net/shellching/archive/2010/04/20/5506019.aspx</a><img src ="http://www.cppblog.com/flyinghare/aggbug/147331.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2011-05-27 09:15 <a href="http://www.cppblog.com/flyinghare/archive/2011/05/27/147331.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++操作符的优先级</title><link>http://www.cppblog.com/flyinghare/archive/2011/04/19/144541.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Tue, 19 Apr 2011 05:46:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2011/04/19/144541.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/144541.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2011/04/19/144541.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/144541.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/144541.html</trackback:ping><description><![CDATA[<table style="LINE-HEIGHT: 1.5" border=0 cellSpacing=1 cellPadding=3 bgColor=#999999>
    <tbody>
        <tr>
            <td bgColor=#cccccc vAlign=top colSpan=4>
            <p align=center><font face="Courier New"><font size=3><strong>C++</strong><strong>操作符的优先级 </strong></font></font></p>
            </td>
        </tr>
        <tr>
            <td bgColor=#ffffff vAlign=top colSpan=2>
            <p align=center><font face="Courier New"><font size=3><strong>操作符及其结合性</strong><strong> </strong></font></font></p>
            </td>
            <td bgColor=#ffffff vAlign=top width=195>
            <p align=center><font face="Courier New"><font size=3><strong>功能</strong><strong> </strong></font></font></p>
            </td>
            <td bgColor=#ffffff vAlign=top width=168>
            <p align=center><font face="Courier New"><font size=3><strong>用法</strong><strong> </strong></font></font></p>
            </td>
        </tr>
        <tr>
            <td bgColor=#ffffff vAlign=top width=43><font size=3 face="Courier New">L<br>L<br>L</font></td>
            <td bgColor=#ffffff vAlign=top width=81><font size=3 face="Courier New">::<br>::<br>::</font></td>
            <td bgColor=#ffffff vAlign=top width=195><font size=3 face="Courier New">全局作用域 <br>类作用域 <br>名字空间作用域 </font></td>
            <td bgColor=#ffffff vAlign=top width=168><font size=3 face="Courier New">::name<br>class::name<br>namespace::name</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff vAlign=top width=43><font size=3 face="Courier New">L<br>L<br>L<br>L<br>L<br></font></td>
            <td bgColor=#ffffff vAlign=top width=81><font size=3 face="Courier New">.<br>-&gt;<br>[]<br>()<br>()<br></font></td>
            <td bgColor=#ffffff vAlign=top width=195><font size=3 face="Courier New">成员选择 <br>成员选择 <br>下标 <br>函数调用 <br>类型构造 <br></font></td>
            <td bgColor=#ffffff vAlign=top width=168><font size=3 face="Courier New">object.member<br>pointer-&gt;member<br>variable[expr]<br>name(expr_list)<br>type(expr_list)</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff vAlign=top width=43><font size=3 face="Courier New">R<br>R<br>R<br>R<br>R<br></font></td>
            <td bgColor=#ffffff vAlign=top width=81><font size=3 face="Courier New">++<br>--<br>typeid<br>typeid<br>显示强制类型转换 <br></font></td>
            <td bgColor=#ffffff vAlign=top width=195><font size=3 face="Courier New">后自增操作 <br>后自减操作 <br>类型ID<br>运行时类型ID<br>类型转换 <br></font></td>
            <td bgColor=#ffffff vAlign=top width=168><font size=3 face="Courier New">lvalue++<br>lvalue--<br>typeid(type)<br>typeid(expr)<br>cast_name&lt;type&gt;(expr)</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff vAlign=top width=43><font size=3 face="Courier New">R<br>R<br>R<br>R<br>R<br>R<br>R<br>R<br>R<br>R<br>R<br>R<br>R<br>R</font></td>
            <td bgColor=#ffffff vAlign=top width=81><font size=3 face="Courier New">sizeof<br>sizeof<br>++<br>--<br>~<br>!<br>-<br>+<br>*<br>&amp;<br>()<br>new<br>delete<br>delete[]</font></td>
            <td bgColor=#ffffff vAlign=top width=195><font size=3 face="Courier New">对象的大小 <br>类型的大小 <br>前自增操作 <br>前自减操作 <br>位求反 <br>逻辑非 <br>一元负号 <br>一元正号 <br>解引用 <br>取地址 <br>类型转换 <br>创建对象 <br>释放对象 <br>释放数组 </font></td>
            <td bgColor=#ffffff vAlign=top width=168><font size=3 face="Courier New">sizeof expr<br>sizeof(type)<br>++lvalue<br>--lvalue<br>~expr<br>!expr<br>-expr<br>+expr<br>*expr<br>&amp;expr<br>(type)expr<br>new type<br>delete expr<br>delete []expr</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff vAlign=top width=43><font size=3 face="Courier New">L<br>L</font></td>
            <td bgColor=#ffffff vAlign=top width=81><font size=3 face="Courier New">-&gt;*<br>.*</font></td>
            <td bgColor=#ffffff vAlign=top width=195><font size=3 face="Courier New">指向成员操作的指针 <br>指向成员操作的指针 </font></td>
            <td bgColor=#ffffff vAlign=top width=168><font size=3 face="Courier New">ptr-&gt;*ptr_to_member<br>obj.*ptr_to_member</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff vAlign=top width=43><font size=3 face="Courier New">L<br>L<br>L</font></td>
            <td bgColor=#ffffff vAlign=top width=81><font size=3 face="Courier New">*<br>/<br>%</font></td>
            <td bgColor=#ffffff vAlign=top width=195><font size=3 face="Courier New">乘法 <br>除法 <br>求模（求余） </font></td>
            <td bgColor=#ffffff vAlign=top width=168><font size=3 face="Courier New">expr * expr<br>expr / expr<br>expr % expr</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff vAlign=top width=43><font size=3 face="Courier New">L<br>L</font></td>
            <td bgColor=#ffffff vAlign=top width=81><font size=3 face="Courier New">+<br>-</font></td>
            <td bgColor=#ffffff vAlign=top width=195><font size=3 face="Courier New">加法 <br>减法 </font></td>
            <td bgColor=#ffffff vAlign=top width=168><font size=3 face="Courier New">expr + expr<br>expr - expr</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff vAlign=top width=43><font size=3 face="Courier New">L<br>L</font></td>
            <td bgColor=#ffffff vAlign=top width=81><font size=3 face="Courier New">&lt;&lt; <br>&gt;&gt; </font></td>
            <td bgColor=#ffffff vAlign=top width=195><font size=3 face="Courier New">位左移 <br>位右移</font></td>
            <td bgColor=#ffffff vAlign=top width=168><font size=3 face="Courier New">expr &lt;&lt; expr<br>expr &gt;&gt; expr</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff vAlign=top width=43><font size=3 face="Courier New">L<br>L<br>L<br>L</font></td>
            <td bgColor=#ffffff vAlign=top width=81><font size=3 face="Courier New">&lt; <br>&lt;=<br>&gt; <br>&gt;=</font></td>
            <td bgColor=#ffffff vAlign=top width=195><font size=3 face="Courier New">小于 <br>小于或等于 <br>大于 <br>大于或等于 </font></td>
            <td bgColor=#ffffff vAlign=top width=168><font size=3 face="Courier New">expr &lt; expr<br>expr &lt;= expr<br>expr &gt; expr<br>expr &gt;= expr</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff vAlign=top width=43><font size=3 face="Courier New">L<br>R</font></td>
            <td bgColor=#ffffff vAlign=top width=81><font size=3 face="Courier New">==<br>!=</font></td>
            <td bgColor=#ffffff vAlign=top width=195><font size=3 face="Courier New">相等 <br>不等 </font></td>
            <td bgColor=#ffffff vAlign=top width=168><font size=3 face="Courier New">Expr == expr<br>Expr != expr</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff vAlign=top width=43><font size=3 face="Courier New">R</font></td>
            <td bgColor=#ffffff vAlign=top width=81><font size=3 face="Courier New">&amp;</font></td>
            <td bgColor=#ffffff vAlign=top width=195><font size=3 face="Courier New">位与 </font></td>
            <td bgColor=#ffffff vAlign=top width=168><font size=3 face="Courier New">Expr &amp; expr</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff vAlign=top width=43><font size=3 face="Courier New">R</font></td>
            <td bgColor=#ffffff vAlign=top width=81><font size=3 face="Courier New">^</font></td>
            <td bgColor=#ffffff vAlign=top width=195><font size=3 face="Courier New">位异或 </font></td>
            <td bgColor=#ffffff vAlign=top width=168><font size=3 face="Courier New">Expr ^ expr</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff vAlign=top width=43><font size=3 face="Courier New">R</font></td>
            <td bgColor=#ffffff vAlign=top width=81><font size=3 face="Courier New">|</font></td>
            <td bgColor=#ffffff vAlign=top width=195><font size=3 face="Courier New">位或 </font></td>
            <td bgColor=#ffffff vAlign=top width=168><font size=3 face="Courier New">Expr | expr</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff vAlign=top width=43><font size=3 face="Courier New">R</font></td>
            <td bgColor=#ffffff vAlign=top width=81><font size=3 face="Courier New">&amp;&amp;</font></td>
            <td bgColor=#ffffff vAlign=top width=195><font size=3 face="Courier New">逻辑与 </font></td>
            <td bgColor=#ffffff vAlign=top width=168><font size=3 face="Courier New">Expr &amp;&amp; expr</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff vAlign=top width=43><font size=3 face="Courier New">R</font></td>
            <td bgColor=#ffffff vAlign=top width=81><font size=3 face="Courier New">||</font></td>
            <td bgColor=#ffffff vAlign=top width=195><font size=3 face="Courier New">逻辑或 </font></td>
            <td bgColor=#ffffff vAlign=top width=168><font size=3 face="Courier New">Expr || expr</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff vAlign=top width=43><font size=3 face="Courier New">R</font></td>
            <td bgColor=#ffffff vAlign=top width=81><font size=3 face="Courier New">?:</font></td>
            <td bgColor=#ffffff vAlign=top width=195><font size=3 face="Courier New">条件操作 </font></td>
            <td bgColor=#ffffff vAlign=top width=168><font size=3 face="Courier New">Expr ? expr : expr</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff vAlign=top width=43><font size=3 face="Courier New">R<br>R<br>R<br>R<br>R</font></td>
            <td bgColor=#ffffff vAlign=top width=81><font size=3 face="Courier New">=<br>*=,/=,%=<br>+=,-=<br>&lt;&lt;=,&gt;&gt;=<br>&amp;=,|=,^=</font></td>
            <td bgColor=#ffffff vAlign=top width=195><font size=3 face="Courier New">赋值操作 <br>符合赋值操作 <br><br></font></td>
            <td bgColor=#ffffff vAlign=top width=168><font size=3 face="Courier New">Lvalue= expr<br>Lvalue+= expr<br>&#8230;&#8230; <br><br></font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff vAlign=top width=43><font size=3 face="Courier New">R</font></td>
            <td bgColor=#ffffff vAlign=top width=81><font size=3 face="Courier New">throw</font></td>
            <td bgColor=#ffffff vAlign=top width=195><font size=3 face="Courier New">抛出异常 </font></td>
            <td bgColor=#ffffff vAlign=top width=168><font size=3 face="Courier New">Throw expr</font></td>
        </tr>
        <tr>
            <td bgColor=#ffffff vAlign=top width=43><font size=3 face="Courier New">L</font></td>
            <td bgColor=#ffffff vAlign=top width=81><font size=3 face="Courier New">,</font></td>
            <td bgColor=#ffffff vAlign=top width=195><font size=3 face="Courier New">逗号 </font></td>
            <td bgColor=#ffffff vAlign=top width=168><font size=3 face="Courier New">Expr, expr</font></td>
        </tr>
    </tbody>
</table>
<div><font color=#800080 size=3>记忆方法：</font></div>
<div><font color=#800080 size=3>--摘自《C语言程序设计实用问答》 -吕凤翥 吕 涛著 <br>问题：如何记住运算符的15种优先级和结合性？ <br>解答：C语言中运算符种类比较繁多，优先级有15种，结合性有两种。 <br>如何记忆两种结合性和15种优先级？下面讲述一种记忆方法。 <br>结合性有两种，一种是自左至右，另一种是自右至左，大部分运算符的结合性是自左至右，只有单目运算符、三目运算符的赋值运算符的结合性自右至左。 <br>优先级有15种。记忆方法如下： <br>记住一个最高的：构造类型的元素或成员以及小括号。 <br>记住一个最低的：逗号运算符。 <br>剩余的是一、二、三、赋值。 <br>意思是单目、双目、三目和赋值运算符。 <br>在诸多运算符中，又分为： <br>算术、关系、逻辑。 <br>两种位操作运算符中，移位运算符在算术运算符后边，逻辑位运算符在逻辑运算符的前面。再细分如下： <br>算术运算符分 *，/，%高于+，-。 <br>关系运算符中，》，》=，《，〈=高于==，！=。 <br>逻辑运算符中，除了逻辑求反（！）是单目外，逻辑与（&amp;&amp;）高于逻辑或（||）。 <br>逻辑位运算符中，除了逻辑按位求反（~）外，按位与（&amp;)高于按位半加（^)，高于按位或（|）。 <br>这样就将15种优先级都记住了，再将记忆方法总结如下： <br>去掉一个最高的，去掉一个最低的，剩下的是一、二、三、赋值。双目运算符中，顺序为算术、关系和逻辑，移位和逻辑位插入其中。 <br><br></font>为什么后缀++比*操作符优先级高却后对p加1？&#8221; ——*p++、*++p、++*p和(*p)++中的操作符优先级问题<br>假设 <br>int a[10] <br>p1=a; <br><br>那么 <br>*p++=1; <br>*++p=2; <br>++*p=3; <br>(*p)++=4; <br><br>分别应该怎么按照优先级别运算？ <br>按照书上的说法++ (后置) &gt;++(前置) &gt;* 解引用用 &gt; = 等于 <br>*p++ 是否应该是 现算(p++) 在算* 最后 赋值? <br>求所有的正确的算法 和解答 <br>--------------------------------------------------------------- <br><br>++(后缀)属于&#8220;后缀操作符&#8221;，其优先级高于&#8220;前缀操作符&#8221;。 <br>* 和++(前缀)都属于&#8220;前缀操作符&#8221;，优先级相同，按从左到右结合的顺序。都高于赋值运算符。 <br><br>所以： <br>*p++=1 相当于 (*(p++)) = 1，也就是说++操作于p上，结果为p原来的值，再作*运算，去除引用，再赋为1。总的作用就是把p引用的对象赋值为1，并把p加1。 <br><br>*++p=2 相当于(*(++p)) = 2，也就是说++操作于p上，结果为p加1后的值，再作*运算，去除引用，再赋值为1。总的作用就是把p加1，然后对其引用的对象赋值为2。 <br><br>++*p=3 相当于(++(*p)) = 3，也就是说先对p作*运算去除引用，其结果为p引用的对象，再把这个对象+1，结果还是这个对象，再把它赋值为3。这个表达式要求对象的前缀++操作符的返回值为左值。 <br><br>(*p)++=4 这里有一个强制优等级(括号)，它的级别最高，结果就是((*p)++) = 4，也就是先对p作*运算去除引用，其结果为它引用的对象，然后对这个对象作后缀++操作符，结果为这个对象操作前的值(一般是一个临时变量)，然后把它赋值为4，这个表达式要求对象的后缀++操作符的返回值为左值(整数类型是不符合要求的，只对定义了这个操作符的对象类型才有可能符合要求)。 <br><br>这个问题以C中很难试验出来，在C++中可以用操作符重载的方法看清楚(操作符重载不会改变优先级)： <br><br>#include &lt;iostream&gt; <br><br>class test <br>{ <br>public: <br>test(){} <br>test(int){} <br>test&amp; operator = (const test&amp;){std::cout&lt;&lt;"Assignment of test" &lt;&lt; std::endl; return *this;} <br>test&amp; operator ++ (){std::cout &lt;&lt; "Prefix ++ of test" &lt;&lt; std:: endl; return * this;} <br>test&amp; operator ++ (int) {std::cout &lt;&lt; "Suffix ++ of test" &lt;&lt; std::endl; return *this;} <br>}; <br>class testptr <br>{ <br>test Value; <br>public: <br>testptr&amp; operator = (const test&amp;){std::cout&lt;&lt;"Assignment of testptr" &lt;&lt; std::endl; return *this;} <br>testptr&amp; operator ++ (){std::cout &lt;&lt; "Prefix ++ of testptr" &lt;&lt; std:: endl; return * this;} <br>testptr&amp; operator ++ (int) {std::cout &lt;&lt; "Suffix ++ of testptr" &lt;&lt; std::endl; return *this;} <br>test&amp; operator *(){std::cout&lt;&lt; "Operator * of testptr"&lt;&lt;std::endl; return Value;} <br>}; <br><br>#define TRACK(X) std::cout &lt;&lt;std::endl&lt;&lt;"***** "&lt;&lt; #X &lt;&lt; " *****" &lt;&lt;std::endl; X <br>int main() <br>{ <br>testptr p; <br>TRACK(*p++=1); <br>TRACK(*++p=2); <br>TRACK(++*p=3); <br>TRACK((*p)++=4); <br>std::cin.get(); <br>} <br><br>输出为 <br>***** *p++=1 ***** <br>Suffix ++ of testptr <br>Operator * of testptr <br>Assignment of test <br><br>***** *++p=2 ***** <br>Prefix ++ of testptr <br>Operator * of testptr <br>Assignment of test <br><br>***** ++*p=3 ***** <br>Operator * of testptr <br>Prefix ++ of test <br>Assignment of test <br><br>***** (*p)++=4 ***** <br>Operator * of testptr <br>Suffix ++ of test <br>Assignment of test <br><br><br>int p = 1; <br>int a = p++; <br>结果a=1，并不是因为后缀++优先级低(我记得有一本C教材就是这样写的，真是误人子弟)，而是由后缀++的语义决定的。标准的后缀++应该是 &#8220;对操作对象做+1操作，并返回操作前的值&#8221;，它在赋值运算前运算了，但它的返回值并不是p，而是p在做+1运算前的值。因此我们还可以知道，p++的返回值应该不是一个左值，p++=a是无法编译通过的。而前缀++则不一样，++p的含义就是&#8220;对p做+1运算，并返回p&#8221;，其返回值就是p本身(引用)，是一个左值，++p = a是可以编译的(但没什么意义)。 <br><br>如果用代码描述一下这两个操作符，应该是这样的： <br><br>const int int::operator ++(int)//后缀++ <br>{ <br>int temp = *this; <br>*this = *this +1; <br>return temp; <br>} <br><br>int&amp; int::operator ++()//前缀++ <br>{ <br>*this = *this + 1; <br>return *this; <br>} <br><br><br>补充： <br>在C中，上述语句含义分别是： <br>*p++=1;　--&gt; temp = p + 1; *temp = 1; <br>*++p=2; --&gt; p = p +1; * p = 1; <br>++*p=3; --&gt; *p = *p + 1; *p = 3; <br>(*p)++=4;//语法错误，无法写出对应的语句。 <br><br>由于后缀增/减量操作符的特殊性，导致初学者很难理解&#8220;为什么后缀的++优先级高却后对变量加1呢？&#8221;事实上，事实上，&#8220;后缀++&#8221;并不是后对变量加1，而是先做了，只是它的返回值并不是这个变量，而是这个变量改变前的值。如果对它很难理解，建议不要使用这几个操作符，而改用普通的加/减法操作符： <br>*p++=1;　--&gt; *p = 1; p = p + 1; <br>*++p=2; --&gt; p = p + 1; *p = 2; <br>++*p=3; --&gt; *p = *p + 1; *p = 3; <br>(*p)++=4;//语法错误，无法写出对应的语句。 <br><br>由于在C++中这几个操作符不再是整数和指针类型特有的，而是可以为类定义的，并且它们可以和+/-1操作语义不同或根本没有加/减法操作符(如双向迭代器)，不能简单地用加/减法代替。不过C++程序员们可以通过看比较好的类的操作符重载函数(如迭代器的)代码真正明白后缀增/减量操作符的语义，不会因为它&#8220;优先级高却后对变量加1&#8221;的问题糊涂。不过，仅管如此，我还是认为使用增/减量操作符时最好让一个表达式中或者没有增/减量操作符，或者只有一个增/减量操作符，如：++p;*p = 1;(相当于*++p = 1)或*p = 1;++p;(相当于*p++=1)，这样也不用去区分前缀和后缀的区别了。 <br></div>
<br><br><br>转自：<a href="http://blog.163.com/wjh2-316/blog/static/2787275320086810153137/">http://blog.163.com/wjh2-316/blog/static/2787275320086810153137/</a>
<img src ="http://www.cppblog.com/flyinghare/aggbug/144541.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2011-04-19 13:46 <a href="http://www.cppblog.com/flyinghare/archive/2011/04/19/144541.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>W2A堆栈溢出</title><link>http://www.cppblog.com/flyinghare/archive/2011/04/19/144522.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Tue, 19 Apr 2011 02:48:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2011/04/19/144522.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/144522.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2011/04/19/144522.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/144522.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/144522.html</trackback:ping><description><![CDATA[<span style="WIDOWS: 2; TEXT-TRANSFORM: none; TEXT-INDENT: 0px; LETTER-SPACING: normal; BORDER-COLLAPSE: separate; FONT: medium Simsun; WHITE-SPACE: normal; ORPHANS: 2; COLOR: rgb(0,0,0); WORD-SPACING: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class=Apple-style-span><span style="TEXT-ALIGN: center; LINE-HEIGHT: 18px; FONT-FAMILY: Arial; FONT-SIZE: 12px" class=Apple-style-span>
<div style="TEXT-ALIGN: left; FILTER: none; BORDER-LEFT: rgb(101,75,34) 5px solid; LINE-HEIGHT: 20px !important; OVERFLOW-X: hidden; OVERFLOW-Y: hidden; TEXT-INDENT: 10px; ZOOM: 1 !important; FONT-FAMILY: Tahoma; WORD-WRAP: break-word; VISIBILITY: visible !important; COLOR: rgb(70,65,45); FONT-SIZE: 13px; WORD-BREAK: break-all; FONT-WEIGHT: bold" class=tit>数据统计工具制作小结－－W2A堆栈溢出</div>
<div style="TEXT-ALIGN: left; FILTER: none; BORDER-LEFT: rgb(0,0,0) 5px solid; LINE-HEIGHT: 20px !important; MARGIN: -3px 0px 8px; PADDING-LEFT: 10px; ZOOM: 1 !important; FONT-FAMILY: Tahoma; WORD-WRAP: break-word; VISIBILITY: visible !important; COLOR: rgb(166,168,167); FONT-SIZE: 11px; WORD-BREAK: break-all" class=date>2010-12-22 17:32</div>
<table style="LINE-HEIGHT: 20px !important; WIDTH: 760px; TABLE-LAYOUT: fixed">
    <tbody style="LINE-HEIGHT: 20px !important">
        <tr style="LINE-HEIGHT: 20px !important">
            <td style="FILTER: none; LINE-HEIGHT: 20px !important; ZOOM: 1 !important; FONT-FAMILY: Arial; WORD-WRAP: break-word; VISIBILITY: visible !important; FONT-SIZE: 12px; WORD-BREAK: break-all">
            <div style="POSITION: static; FILTER: none; LINE-HEIGHT: 20px; OVERFLOW-X: hidden; OVERFLOW-Y: hidden; ZOOM: 1 !important; FONT-FAMILY: Tahoma; WORD-WRAP: break-word; VISIBILITY: visible !important; COLOR: rgb(70,65,45); FONT-SIZE: 12px; WORD-BREAK: normal" id=blog_text class=cnt>
            <p style="LINE-HEIGHT: normal">在测试大数据量的时候，因为我的程序最后要生成一个excel报表，可是每次打开的时候，explorer.exe就报错，我在想，我又没惹你，你怎么不给打开呢，难道是我用的ODBC数据操作有误？想想不对，数据不大的时候怎么没事呢？没办法，拿个大数据文件debug吧！结果好不容易遇到一个CString错误，说程序溢出，当时忙着改错，没有记录下来错误描述。记得那个长长的错误提示中包含有W2A字样，好！因为我用到了W2A的宏！立马回忆起来曾经用它时遇到的问题，查了一下MSDN，《TN059: Using MFC MBCS/Unicode Conversion Macros&nbsp; 》，Link:<a style="LINE-HEIGHT: 20px; FONT-FAMILY: Tahoma; COLOR: rgb(70,65,45); FONT-SIZE: 12px; TEXT-DECORATION: none" href="http://msdn.microsoft.com/en-us/library/805c56f8%28VS.80%29.aspx">http://msdn.microsoft.com/en-us/library/805c56f8%28VS.80%29.aspx</a></p>
            <p style="LINE-HEIGHT: normal">讲得非常详细，就是W2A是在栈上取得一段内存，在程序结束时栈才会释放取得的栈空间，所以，不能在一个大的循环中使用它，而应该在程序外面专门写一个字符串处理小函数，达到快速、安全转换的目的。</p>
            </div>
            </td>
        </tr>
    </tbody>
</table>
</span></span><br><br>转自：<a href="http://hi.baidu.com/lyzneuq/blog/item/1a5907df4f81744594ee374f.html"><u><font color=#0066cc>http://hi.baidu.com/lyzneuq/blog/item/1a5907df4f81744594ee374f.html</font></u></a>
<img src ="http://www.cppblog.com/flyinghare/aggbug/144522.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2011-04-19 10:48 <a href="http://www.cppblog.com/flyinghare/archive/2011/04/19/144522.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>对“仅通过崩溃地址找出源代码的出错行”一文的补充与改进</title><link>http://www.cppblog.com/flyinghare/archive/2011/04/06/143526.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Wed, 06 Apr 2011 07:16:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2011/04/06/143526.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/143526.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2011/04/06/143526.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/143526.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/143526.html</trackback:ping><description><![CDATA[作者：<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#116;&#120;&#113;&#99;&#52;&#64;&#115;&#111;&#104;&#117;&#46;&#99;&#111;&#109;"><font color=#1d58d1>上海伟功通信 roc</font></a>
<p><a href="http://www.vckbase.com/code/downcode.asp?id=2691"><font color=#1d58d1>下载源代码</font></a><br><br>读了老罗的&#8220;<a href="http://www.vckbase.com/document/viewdoc/?id=908" target=_blank><font color=#1d58d1>仅通过崩溃地址找出源代码的出错行</font></a>&#8221;(下称"罗文")一文后，感觉该文还是可以学到不少东西的。不过文中尚存在有些说法不妥，以及有些操作太繁琐的地方。为此，本人在学习了此文后，在多次实验实践基础上，把该文中的一些内容进行补充与改进，希望对大家调试程序，尤其是release版本的程序有帮助。欢迎各位朋友批评指正。<br><br><br><strong>一、该方法适用的范围</strong><br>在windows程序中造成程序崩溃的原因很多，而文中所述的方法仅适用与:由一条语句当即引起的程序崩溃。如原文中举的除数为零的崩溃例子。而笔者在实际工作中碰到更多的情况是:指针指向一非法地址，然后对指针的内容进行了，读或写的操作。例如：<br></p>
<pre>void Crash1()<br>
{<br>
char * p =(char*)100;<br>
*p=100;<br>
}<br>
</pre>
这些原因造成的崩溃，无论是debug版本，还是release版本的程序，使用该方法都可找到造成崩溃的函数或子程序中的语句行，具体方法的下面还会补充说明。另外，实践中另一种常见的造成程序崩溃的原因:函数或子程序中局部变量数组越界付值，造成函数或子程序返回地址遭覆盖，从而造成函数或子程序返回时崩溃。例如:<br>
<pre>#include <string.h><br>
void Crash2();<br>
int main(int argc,char* argv[])<br>
{<br>
Crash2();<br>
return 0;<br>
}<br>
<br>
void Crash2()<br>
{<br>
char p[1];<br>
strcpy(p,"0123456789");<br>
}<br>
</string.h></pre>
在vc中编译运行此程序的release版本，会跳出如下的出错提示框。 <br><br><img border=0 alt="" src="http://www.vckbase.com/document/journal/vckbase42/images/crashimg1.jpg" width=434 height=139><br>图一 上面例子运行结果<br><br>这里显示的崩溃地址为:0x34333231。这种由前面语句造成的崩溃根源，在后续程序中方才显现出来的情况，显然用该文所述的方法就无能为力了。不过在此例中多少还有些蛛丝马迹可寻找到崩溃的原因:函数Crash2中的局部数组p只有一个字节大小，显然拷贝"0123456789"这个字符串会把超出长度的字符串拷贝到数组p的后面，即*(p+1)=''1''，*(p+2)=''2''，* (p+3)=''3''，*(p+4)=4。。。。。。而字符''1''的ASC码的值为0x31，''2''为0x32，''3''为 0x33，''4''为0x34。。。。。，由于intel的cpu中int型数据是低字节保存在低地址中，所以保存字符串''1234''的内存，显示为一个4字节的int型数时就是0x34333231。显然拷贝"0123456789"这个字符串时，"1234"这几个字符把函数Crash2的返回地址给覆盖，从而造成程序崩溃。对于类似的这种造成程序崩溃的错误朋友们还有其他方法排错的话，欢迎一起交流讨论。<br><br><br><strong>二、设置编译产生map文件的方法</strong><br>该文中产生map文件的方法是手工添加编译参数来产生map文件。其实在vc6的IDE中有产生map文件的配置选项的。操作如下:先点击菜单"Project"-&gt;"Settings。。。"，弹出的属性页中选中"Link"页，确保在"category"中选中"General"，最后选中"Generate mapfile"的可选项。若要在在map文件中显示Line numbers的信息的话，还需在project options 中加入/mapinfo:lines 。Line numbers信息对于"罗文"所用的方法来定位出错源代码行很重要，但笔者后面会介绍更加好的方法来定位出错代码行，那种方法不需要Line numbers信息。 <br><br><img border=0 alt="" src="http://www.vckbase.com/document/journal/vckbase42/images/crashimg3.JPG" width=677 height=446><br>图二 设置产生MAP文件 <br><br><br><strong>三、定位崩溃语句位置的方法</strong><br>"罗文"所述的定位方法中，找到产生崩溃的函数位置的方法是正确的，即在map文件列出的每个函数的起始地址中，最近的且不大于崩溃地址的地址即为包含崩溃语句的函数的地址。但之后的再进一步的定位出错语句行的方法不是最妥当，因为那种方法前提是，假设基地址的值是 0x00400000 ，以及一般的 PE 文件的代码段都是从 0x1000偏移开始的。虽然这种情况很普遍，但在vc中还是可以基地址设置为其他数，比如设置为0x00500000，这时仍旧套用<br>
<pre> 崩溃行偏移 = 崩溃地址 - 0x00400000 - 0x1000 </pre>
的公式显然无法找到崩溃行偏移。 其实上述公式若改为<br>
<pre>崩溃行偏移 = 崩溃地址 - 崩溃函数绝对地址 + 函数相对偏移</pre>
即可通用了。仍以"罗文"中的例子为例:"罗文"中提到的在其崩溃程序的对应map文件中，崩溃函数的编译结果为<br>
<pre>0001:00000020 ?Crash@@YAXXZ 00401020 f CrashDemo。obj </pre>
对与上述结果，在使用我的公式时，"崩溃函数绝对地址"指00401020， 函数相对偏移指 00000020，当崩溃地址= 0x0040104a时， 则 崩溃行偏移 = 崩溃地址 - 崩溃函数起始地址+ 函数相对偏移 = 0x0040104a - 0x00401020 + 0x00000020= 0x4a，结果与"罗文"计算结果相同。但这个公式更通用。<br><br><br><strong>四、更好的定位崩溃语句位置的方法。</strong><br>其实除了依靠map文件中的Line numbers信息最终定位出错语句行外，在vc6中我们还可以通过编译程序产生的对应的汇编语句，二进制码，以及对应c/c++语句为一体的"cod"文件来定位出错语句行。先介绍一下产生这种包含了三种信息的"cod"文件的设置方法:先点击菜单"Project"-&gt;"Settings。。。"，弹出的属性页中选中"C/C++"页，然后在"Category"中选则"Listing Files"，再在"Listing file type"的组合框中选择"Assembly，Machine code， and source"。接下去再通过一个具体的例子来说明这种方法的具体操作。 <br><br><img border=0 alt="" src="http://www.vckbase.com/document/journal/vckbase42/images/crashimg4.JPG" width=677 height=446><br>图三 设置产生"cod"文件 <br><br>准备步骤1)产生崩溃的程序如下:<br>
<pre>01 //****************************************************************<br>
02 //文件名称：crash。cpp<br>
03 //作用:    演示通过崩溃地址找出源代码的出错行新方法<br>
04 //作者：   伟功通信 roc<br>
05 //日期：   2005-5-16<br>
06//****************************************************************<br>
07 void Crash1();<br>
08 int main(int argc,char* argv[])<br>
09 {<br>
10	Crash1();<br>
11	return 0;<br>
12 }<br>
13<br>
14 void Crash1()<br>
15 {<br>
16  char * p =(char*)100;<br>
17  *p=100;<br>
18 }<br>
</pre>
准备步骤2)按本文所述设置产生map文件(不需要产生Line numbers信息)。<br>准备步骤3)按本文所述设置产生cod文件。<br>准备步骤4)编译。这里以debug版本为例(若是release版本需要将编译选项改为不进行任何优化的选项，否则上述代码会因为优化时看作废代码而不被编译，从而看不到崩溃的结果)，编译后产生一个"exe"文件，一个"map"文件，一个"cod"文件。 <br>运行此程序，产生如下如下崩溃提示: <br><br><img border=0 alt="" src="http://www.vckbase.com/document/journal/vckbase42/images/crashimg2.JPG" width=434 height=139><br>图四 上面例子运行结果 <br><br>排错步骤1)定位崩溃函数。可以查询map文件获得。我的机器编译产生的map文件的部分如下:<br>
<pre> Crash<br>
<br>
Timestamp is 42881a01 (Mon May 16 11:56:49 2005)<br>
<br>
Preferred load address is 00400000<br>
<br>
Start Length Name Class<br>
0001:00000000 0000ddf1H .text CODE<br>
0001:0000ddf1 0001000fH .textbss CODE<br>
0002:00000000 00001346H .rdata DATA<br>
0002:00001346 00000000H .edata DATA<br>
0003:00000000 00000104H .CRT$XCA DATA<br>
0003:00000104 00000104H .CRT$XCZ DATA<br>
0003:00000208 00000104H .CRT$XIA DATA<br>
0003:0000030c 00000109H .CRT$XIC DATA<br>
0003:00000418 00000104H .CRT$XIZ DATA<br>
0003:0000051c 00000104H .CRT$XPA DATA<br>
0003:00000620 00000104H .CRT$XPX DATA<br>
0003:00000724 00000104H .CRT$XPZ DATA<br>
0003:00000828 00000104H .CRT$XTA DATA<br>
0003:0000092c 00000104H .CRT$XTZ DATA<br>
0003:00000a30 00000b93H .data DATA<br>
0003:000015c4 00001974H .bss DATA<br>
0004:00000000 00000014H .idata$2 DATA<br>
0004:00000014 00000014H .idata$3 DATA<br>
0004:00000028 00000110H .idata$4 DATA<br>
0004:00000138 00000110H .idata$5 DATA<br>
0004:00000248 000004afH .idata$6 DATA<br>
<br>
Address Publics by Value Rva+Base Lib:Object<br>
<br>
0001:00000020 _main 00401020 f Crash.obj<br>
0001:00000060 ?Crash1@@YAXXZ 00401060 f Crash.obj<br>
0001:000000a0 __chkesp 004010a0 f LIBCD:chkesp.obj<br>
0001:000000e0 _mainCRTStartup 004010e0 f LIBCD:crt0.obj<br>
0001:00000210 __amsg_exit 00401210 f LIBCD:crt0.obj<br>
0001:00000270 __CrtDbgBreak 00401270 f LIBCD:dbgrpt.obj<br>
...<br>
</pre>
对于崩溃地址0x00401082而言，小于此地址中最接近的地址(Rva+Base中的地址)为00401060，其对应的函数名为?Crash1@@YAXXZ，由于所有以问号开头的函数名称都是 C++ 修饰的名称，"@@YAXXZ"则为区别重载函数而加的后缀，所以?Crash1@@YAXXZ就是我们的源程序中，Crash1() 这个函数。<br>排错步骤2)定位出错行。打开编译生成的"cod"文件，我机器上生成的文件内容如下:<br>
<pre>	TITLE	E:\Crash\Crash。cpp<br>
.386P<br>
include listing.inc<br>
if @Version gt 510<br>
.model FLAT<br>
else<br>
_TEXT	SEGMENT PARA USE32 PUBLIC ''CODE''<br>
_TEXT	ENDS<br>
_DATA	SEGMENT DWORD USE32 PUBLIC ''DATA''<br>
_DATA	ENDS<br>
CONST	SEGMENT DWORD USE32 PUBLIC ''CONST''<br>
CONST	ENDS<br>
_BSS	SEGMENT DWORD USE32 PUBLIC ''BSS''<br>
_BSS	ENDS<br>
$$SYMBOLS	SEGMENT BYTE USE32 ''DEBSYM''<br>
$$SYMBOLS	ENDS<br>
$$TYPES	SEGMENT BYTE USE32 ''DEBTYP''<br>
$$TYPES	ENDS<br>
_TLS	SEGMENT DWORD USE32 PUBLIC ''TLS''<br>
_TLS	ENDS<br>
;	COMDAT _main<br>
_TEXT	SEGMENT PARA USE32 PUBLIC ''CODE''<br>
_TEXT	ENDS<br>
;	COMDAT ?Crash1@@YAXXZ<br>
_TEXT	SEGMENT PARA USE32 PUBLIC ''CODE''<br>
_TEXT	ENDS<br>
FLAT	GROUP _DATA， CONST, _BSS<br>
ASSUME	CS: FLAT, DS: FLAT, SS: FLAT<br>
endif<br>
PUBLIC	?Crash1@@YAXXZ					; Crash1<br>
PUBLIC	_main<br>
EXTRN	__chkesp:NEAR<br>
;	COMDAT _main<br>
_TEXT	SEGMENT<br>
_main	PROC NEAR					; COMDAT<br>
<br>
; 9    : {<br>
<br>
00000	55		 push	 ebp<br>
00001	8b ec		 mov	 ebp， esp<br>
00003	83 ec 40	 sub	 esp, 64			; 00000040H<br>
00006	53		 push	 ebx<br>
00007	56		 push	 esi<br>
00008	57		 push	 edi<br>
00009	8d 7d c0	 lea	 edi, DWORD PTR [ebp-64]<br>
0000c	b9 10 00 00 00	 mov	 ecx， 16			; 00000010H<br>
00011	b8 cc cc cc cc	 mov	 eax， -858993460		; ccccccccH<br>
00016	f3 ab		 rep stosd<br>
<br>
; 10   : 	Crash1();<br>
<br>
00018	e8 00 00 00 00	 call	 ?Crash1@@YAXXZ		; Crash1<br>
<br>
; 11   : 	return 0;<br>
<br>
0001d	33 c0		 xor	 eax， eax<br>
<br>
; 12   : }<br>
<br>
0001f	5f		 pop	 edi<br>
00020	5e		 pop	 esi<br>
00021	5b		 pop	 ebx<br>
00022	83 c4 40	 add	 esp, 64			; 00000040H<br>
00025	3b ec		 cmp	 ebp, esp<br>
00027	e8 00 00 00 00	 call	 __chkesp<br>
0002c	8b e5		 mov	 esp, ebp<br>
0002e	5d		 pop	 ebp<br>
0002f	c3		 ret	 0<br>
_main	ENDP<br>
_TEXT	ENDS<br>
;	COMDAT ?Crash1@@YAXXZ<br>
_TEXT	SEGMENT<br>
_p$ = -4<br>
?Crash1@@YAXXZ PROC NEAR				; Crash1, COMDAT<br>
<br>
; 15   : {<br>
<br>
00000	55		 push	 ebp<br>
00001	8b ec		 mov	 ebp, esp<br>
00003	83 ec 44	 sub	 esp, 68			; 00000044H<br>
00006	53		 push	 ebx<br>
00007	56		 push	 esi<br>
00008	57		 push	 edi<br>
00009	8d 7d bc	 lea	 edi, DWORD PTR [ebp-68]<br>
0000c	b9 11 00 00 00	 mov	 ecx, 17			; 00000011H<br>
00011	b8 cc cc cc cc	 mov	 eax, -858993460		; ccccccccH<br>
00016	f3 ab		 rep stosd<br>
<br>
; 16   :  char * p =(char*)100;<br>
<br>
00018	c7 45 fc 64 00<br>
00 00		 mov	 DWORD PTR _p$[ebp], 100	; 00000064H<br>
<br>
; 17   :  *p=100;<br>
<br>
0001f	8b 45 fc	 mov	 eax, DWORD PTR _p$[ebp]<br>
00022	c6 00 64	 mov	 BYTE PTR [eax], 100	; 00000064H<br>
<br>
; 18   : }<br>
<br>
00025	5f		 pop	 edi<br>
00026	5e		 pop	 esi<br>
00027	5b		 pop	 ebx<br>
00028	8b e5		 mov	 esp, ebp<br>
0002a	5d		 pop	 ebp<br>
0002b	c3		 ret	 0<br>
?Crash1@@YAXXZ ENDP					; Crash1<br>
_TEXT	ENDS<br>
END<br>
</pre>
其中<br>
<pre>?Crash1@@YAXXZ PROC NEAR				; Crash1, COMDAT</pre>
为Crash1汇编代码的起始行。产生崩溃的代码便在其后的某个位置。接下去的一行为: <br>
<pre>; 15   : {</pre>
冒号后的"{"表示源文件中的语句，冒号前的"15"表示该语句在源文件中的行数。这之后显示该语句汇编后的偏移地址，二进制码，汇编代码。如 <br>
<pre>00000	55		 push	 ebp</pre>
其中"0000"表示相对于函数开始地址后的偏移，"55"为编译后的机器代码，" push ebp"为汇编代码。从"cod"文件中我们可以看出，一条(c/c++)语句通常需要编译成数条汇编语句。此外有些汇编语句太长则会分两行显示如: <br>
<pre>00018	c7 45 fc 64 00<br>
00 00		 mov	 DWORD PTR _p$[ebp], 100	; 00000064H</pre>
其中"0018"表示相对偏移，在debug版本中，这个数据为相对于函数起始地址的偏移(此时每个函数第一条语句相对偏移为0000)；release版本中为相对于代码段第一条语句的偏移(即代码段第一条语句相对偏移为0000，而以后的每个函数第一条语句相对偏移就不为0000了)。"c7 45 fc 64 00 00 00 "为编译后的机器代码 ，"mov DWORD PTR _p$[ebp]， 100"为汇编代码，汇编语言中";"后的内容为注释，所以";00000064H"，是个注释这里用来说明100转换成16进制时为"00000064H"。<br>接下去，我们开始来定位产生崩溃的语句。<br>第一步，计算崩溃地址相对于崩溃函数的偏移，在本例中已经知道了崩溃语句的地址(0x00401082)，和对应函数的起始地址(0x00401060)，所以崩溃地址相对函数起始地址的偏移就很容易计算了: <br>
<pre>  崩溃偏移地址 = 崩溃语句地址 - 崩溃函数的起始地址 = 0x00401082 - 0x00401060 = 0x22。</pre>
第二步，计算出错的汇编语句在cod文件中的相对偏移。我们可以看到函数Crash1()在cod文件中的相对偏移地址为0000，则 <br>
<pre>崩溃语句在cod文件中的相对偏移 =  崩溃函数在cod文件中相对偏移 + 崩溃偏移地址 = 0x0000 + 0x22 = 0x22</pre>
第三步，我们看Crash1函数偏移0x22除的代码是什么?结果如下 <br>
<pre> 00022	c6 00 64	 mov	 BYTE PTR [eax], 100	; 00000064H</pre>
这句汇编语句表示将100这个数保存到寄存器eax所指的内存单元中去，保存空间大小为1个字节(byte)。程序正是执行这条命令时产生了崩溃，显然这里eax中的为一个非法地址，所以程序崩溃了!<br>第四步，再查看该汇编语句在其前面几行的其对应的源代码，结果如下: <br>
<pre>; 17   :  *p=100;</pre>
其中17表示该语句位于源文件中第17行，而&#8220;*p=100;&#8221;这正是源文件中产生崩溃的语句。<br>至此我们仅从崩溃地址就查找出了造成崩溃的源代码语句和该语句所在源文件中的确切位置，甚至查找到了造成崩溃的编译后的确切汇编代码!<br>怎么样，是不是感觉更爽啊?<br><br><br><strong>五、小节</strong><br><br>1、新方法同样要注意可以适用的范围，即程序由一条语句当即引起的崩溃。另外我不知道除了VC6外，是否还有其他的编译器能够产生类似的"cod"文件。<br>2、我们可以通过比较 新方法产生的debug和releae版本的"cod"文件，查找那些仅release版本(或debug版本)有另一个版本没有的bug(或其他性状)。例如"罗文"中所举的那个用例，只要打开release版本的"cod"文件，就明白了为啥debug版本会产生崩溃而release版本却没有:原来release版本中产生崩溃的语句其实根本都没有编译。同样本例中的release版本要看到崩溃的效果，需要将编译选项改为为不优化的配置。 <br><br><br>转自：<a href="http://www.cnblogs.com/xxrl/archive/2008/05/06/1185337.html">http://www.cnblogs.com/xxrl/archive/2008/05/06/1185337.html</a>
<script type=text/javascript>
if ($ != jQuery) {
$ = jQuery.noConflict();
}
var isLogined = false;
var cb_blogId = 11030;
var cb_entryId = 1185337;
var cb_blogApp = "xxrl";
var cb_blogUserGuid = "789a310b-63cf-dd11-9e4d-001cf0cd104b";
var cb_entryCreatedDate = '2008/5/6 16:24:00';
</script>
<img src ="http://www.cppblog.com/flyinghare/aggbug/143526.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2011-04-06 15:16 <a href="http://www.cppblog.com/flyinghare/archive/2011/04/06/143526.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>函数的返回类型为指针类型时的若干思考（字符串常量问题）</title><link>http://www.cppblog.com/flyinghare/archive/2011/03/22/142466.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Tue, 22 Mar 2011 04:02:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2011/03/22/142466.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/142466.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2011/03/22/142466.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/142466.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/142466.html</trackback:ping><description><![CDATA[<span style="TEXT-ALIGN: center; WIDOWS: 2; TEXT-TRANSFORM: none; TEXT-INDENT: 0px; LETTER-SPACING: normal; BORDER-COLLAPSE: separate; FONT: medium Simsun; WHITE-SPACE: normal; ORPHANS: 2; COLOR: rgb(0,0,0); WORD-SPACING: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class=Apple-style-span><span style="TEXT-ALIGN: left; LINE-HEIGHT: 22px; FONT-FAMILY: Arial, Helvetica, simsun, u5b8bu4f53; COLOR: rgb(56,56,56); FONT-SIZE: 14px" class=Apple-style-span><font style="LINE-HEIGHT: 51px" color=#02368d size=6 face=song><span style="LINE-HEIGHT: normal; BORDER-COLLAPSE: collapse; FONT-SIZE: 19px"><strong style="LINE-HEIGHT: 30px"><span style="LINE-HEIGHT: normal; COLOR: rgb(0,0,0); FONT-SIZE: 12px; FONT-WEIGHT: normal">By zieckey (http://blog.chinaunix.net/u/16292/index.html)</span></strong></span></font>
<div style="LINE-HEIGHT: 22px"><font style="LINE-HEIGHT: 25px" size=3 face=song><span style="LINE-HEIGHT: normal; BORDER-COLLAPSE: collapse; FONT-SIZE: 12px">问题的引入：<br style="FONT: 12px song, Verdana">看看下面的程序的输出：<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">
<table style="LINE-HEIGHT: 19px; BORDER-COLLAPSE: collapse" border=1 cellSpacing=0 borderColor=#999999 cellPadding=0 width="95%" bgColor=#f1f1f1>
    <tbody style="LINE-HEIGHT: 19px">
        <tr style="FONT: 12px song, Verdana">
            <td style="FONT: 12px song, Verdana">
            <p style="PADDING-BOTTOM: 0px; MARGIN: 5px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; FONT: 12px song, Verdana; PADDING-TOP: 0px"><code style="LINE-HEIGHT: 19px"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,0)"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">#</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,0)">include</span>&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">&lt;</span>stdio<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">.</span>h<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">&gt;</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">char</span>&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">*</span>returnStr<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">{</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">char</span>&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">*</span>p<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">=</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,255)">"hello world!"</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">return</span>&nbsp;p<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">}</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">int</span>&nbsp;main<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">{</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">char</span>&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">*</span>str<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;str<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">=</span>returnStr<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,0)">printf</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,255)">"%s\n"</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">,</span>&nbsp;str<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">return</span>&nbsp;0<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">}</span></span></code></p>
            </td>
        </tr>
    </tbody>
</table>
<br style="FONT: 12px song, Verdana">这个没有任何问题，因为"hello world!"是一个字符串常量，存放在静态数据区，<br style="FONT: 12px song, Verdana">把该字符串常量存放的静态数据区的首地址赋值给了指针，<br style="FONT: 12px song, Verdana">所以returnStr函数退出时，该该字符串常量所在内存不会被回收，故能够通过指针顺利无误的访问。<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">但是，下面的就有问题：<br style="FONT: 12px song, Verdana">
<table style="LINE-HEIGHT: 19px; BORDER-COLLAPSE: collapse" border=1 cellSpacing=0 borderColor=#999999 cellPadding=0 width="95%" bgColor=#f1f1f1>
    <tbody style="LINE-HEIGHT: 19px">
        <tr style="FONT: 12px song, Verdana">
            <td style="FONT: 12px song, Verdana">
            <p style="PADDING-BOTTOM: 0px; MARGIN: 5px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; FONT: 12px song, Verdana; PADDING-TOP: 0px"><code style="LINE-HEIGHT: 19px"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,0)"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">#</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,0)">include</span>&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">&lt;</span>stdio<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">.</span>h<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">&gt;</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">char</span>&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">*</span>returnStr<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">{</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">char</span>&nbsp;p<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">[</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">]</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">=</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,255)">"hello world!"</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">return</span>&nbsp;p<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">}</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">int</span>&nbsp;main<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">{</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">char</span>&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">*</span>str<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;str<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">=</span>returnStr<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,0)">printf</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,255)">"%s\n"</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">,</span>&nbsp;str<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">return</span>&nbsp;0<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">}</span><br style="FONT: 12px song, Verdana"></span></code></p>
            </td>
        </tr>
    </tbody>
</table>
<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,1,255)">"hello world!"是一个字符串常量，存放在静态数据区，没错，</span><br style="FONT: 12px song, Verdana; COLOR: rgb(0,1,255)"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,1,255)">但是把一个字符串常量赋值给了一个局部变量(char []型数组)，该局部变量存放在栈中，</span><br style="FONT: 12px song, Verdana; COLOR: rgb(0,1,255)"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,1,255)">这样就有两块内容一样的内存，</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,1,2); FONT-WEIGHT: bold">也就是说&#8220;</span><code style="LINE-HEIGHT: 19px"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,0)"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">char</span>&nbsp;p<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">[</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">]</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">=</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,255)">"hello world!"</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span></span></code><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,1,2); FONT-WEIGHT: bold">&#8221;这条语句让&#8220;hello world!&#8221;这个字符串在内存中有两份拷贝，<span style="LINE-HEIGHT: 19px; COLOR: rgb(102,1,153)">一份在动态分配的栈中，另一份在静态存储区。</span></span>这是与前着最本质的区别，<br style="FONT: 12px song, Verdana">当returnStr函数退出时，栈要清空，局部变量的内存也被清空了，<br style="FONT: 12px song, Verdana">所以这时的函数返回的是一个已被释放的内存地址，所以打印出来的是乱码。<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">如果函数的返回值非要是一个局部变量的地址，那么该局部变量一定要申明为static类型。如下：<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">
<table style="LINE-HEIGHT: 19px; BORDER-COLLAPSE: collapse" border=1 cellSpacing=0 borderColor=#999999 cellPadding=0 width="95%" bgColor=#f1f1f1>
    <tbody style="LINE-HEIGHT: 19px">
        <tr style="FONT: 12px song, Verdana">
            <td style="FONT: 12px song, Verdana">
            <p style="PADDING-BOTTOM: 0px; MARGIN: 5px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; FONT: 12px song, Verdana; PADDING-TOP: 0px"><code style="LINE-HEIGHT: 19px"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,0)"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">#</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,0)">include</span>&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">&lt;</span>stdio<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">.</span>h<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">&gt;</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">char</span>&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">*</span>returnStr<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">{</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">static</span>&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">char</span>&nbsp;p<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">[</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">]</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">=</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,255)">"hello world!"</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">return</span>&nbsp;p<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">}</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">int</span>&nbsp;main<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">{</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">char</span>&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">*</span>str<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;str<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">=</span>returnStr<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,0)">printf</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,255)">"%s\n"</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">,</span>&nbsp;str<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">return</span>&nbsp;0<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">}</span></span></code></p>
            </td>
        </tr>
    </tbody>
</table>
<br style="FONT: 12px song, Verdana">这个问题可以通过下面的一个例子来更好的说明：<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">
<table style="LINE-HEIGHT: 19px; BORDER-COLLAPSE: collapse" border=1 cellSpacing=0 borderColor=#999999 cellPadding=0 width="95%" bgColor=#f1f1f1>
    <tbody style="LINE-HEIGHT: 19px">
        <tr style="FONT: 12px song, Verdana">
            <td style="FONT: 12px song, Verdana">
            <p style="PADDING-BOTTOM: 0px; MARGIN: 5px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; FONT: 12px song, Verdana; PADDING-TOP: 0px"><code style="LINE-HEIGHT: 19px"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,0)"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">#</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,0)">include</span>&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">&lt;</span>stdio<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">.</span>h<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">&gt;</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,153,0)">//返回的是局部变量的地址，该地址位于动态数据区，栈里<br style="FONT: 12px song, Verdana"></span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">char *s1()<br style="FONT: 12px song, Verdana">{<br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp; char* p1 = "qqq";//为了测试&#8216;</span></span></code><code style="LINE-HEIGHT: 19px"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,0)"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">char p[]="Hello world!"</span></span></code><code style="LINE-HEIGHT: 19px"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,0)"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">&#8217;中的字符串在静态存储区是否也有一份拷贝<br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp; char p[]="Hello world!";<br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp; char* p2 = "w";</span></span></code><code style="LINE-HEIGHT: 19px"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,0)"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">//为了测试&#8216;</span></span></code><code style="LINE-HEIGHT: 19px"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,0)"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">char p[]="Hello world!"</span></span></code><code style="LINE-HEIGHT: 19px"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,0)"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">&#8217;中的字符串在静态存储区是否也有一份拷贝</span></span></code><br style="FONT: 12px song, Verdana"><code style="LINE-HEIGHT: 19px"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,0)"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">&nbsp;&nbsp;&nbsp; printf("in s1 p=%p\n", p);<br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp; printf("in s1 p1=%p\n", p1);<br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp; printf("in s1: string's address: %p\n", &amp;("Hello world!"));<br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp; printf("in s1 p2=%p\n", p2);<br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp; return p;<br style="FONT: 12px song, Verdana">}</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)"></span><br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,153,0)">//返回的是字符串常量的地址，该地址位于静态数据区<br style="FONT: 12px song, Verdana"></span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">char</span>&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">*</span>s2<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">{</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">char</span>&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">*</span>q<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">=</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,255)">"Hello world!"</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,0)">printf</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,255)">"in s2 q=%p\n"</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">,</span>&nbsp;q<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,0)">printf</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,255)">"in s2: string's address: %p\n"</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">,</span>&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">&amp;</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,255)">"Hello world!"</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">return</span>&nbsp;q<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">}</span><br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,153,0)">//返回的是静态局部变量的地址，该地址位于静态数据区<br style="FONT: 12px song, Verdana"></span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">char</span>&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">*</span>s3<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">{</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">static</span>&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">char</span>&nbsp;r<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">[</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">]</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">=</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,255)">"Hello world!"</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,0)">printf</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,255)">"in s3 r=%p\n"</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">,</span>&nbsp;r<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,0)">printf</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,255)">"in s3: string's address: %p\n"</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">,</span>&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">&amp;</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,255)">"Hello world!"</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">return</span>&nbsp;r<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">}</span><br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">int</span>&nbsp;main<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">{</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">char</span>&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">*</span>t1<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">,</span>&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">*</span>t2<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">,</span>&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">*</span>t3<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;t1<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">=</span>s1<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;t2<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">=</span>s2<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;t3<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">=</span>s3<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,0)">printf</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,255)">"in main:"</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,0)">printf</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,255)">"p=%p, q=%p, r=%p\n"</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">,</span>&nbsp;t1<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">,</span>&nbsp;t2<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">,</span>&nbsp;t3<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,0)">printf</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,255)">"%s\n"</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">,</span>&nbsp;t1<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,0)">printf</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,255)">"%s\n"</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">,</span>&nbsp;t2<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,0)">printf</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">(</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,0,255)">"%s\n"</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">,</span>&nbsp;t3<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">)</span><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">return</span>&nbsp;0<span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,204)">}</span><br style="FONT: 12px song, Verdana"></span></code></p>
            </td>
        </tr>
    </tbody>
</table>
运行输出结果：<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">
<table style="LINE-HEIGHT: 19px; BORDER-COLLAPSE: collapse" border=1 cellSpacing=0 borderColor=#999999 cellPadding=0 width="95%" bgColor=#f1f1f1>
    <tbody style="LINE-HEIGHT: 19px">
        <tr style="FONT: 12px song, Verdana">
            <td style="FONT: 12px song, Verdana">
            <p style="PADDING-BOTTOM: 0px; MARGIN: 5px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; FONT: 12px song, Verdana; PADDING-TOP: 0px"><code style="LINE-HEIGHT: 19px"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,0)"><span style="LINE-HEIGHT: 19px; COLOR: rgb(0,0,255)">in s1 p=0013FF0C<br style="FONT: 12px song, Verdana">in s1 p1=00431084<br style="FONT: 12px song, Verdana">in s1: string's address: 00431074<br style="FONT: 12px song, Verdana">in s1 p2=00431070<br style="FONT: 12px song, Verdana">in s2 q=00431074<br style="FONT: 12px song, Verdana">in s2: string's address: 00431074<br style="FONT: 12px song, Verdana">in s3 r=00434DC0<br style="FONT: 12px song, Verdana">in s3: string's address: 00431074<br style="FONT: 12px song, Verdana">in main:p=0013FF0C, q=00431074, r=00434DC0<br style="FONT: 12px song, Verdana">$?<br style="FONT: 12px song, Verdana">Hello world!<br style="FONT: 12px song, Verdana">Hello world!</span></span></code></p>
            </td>
        </tr>
    </tbody>
</table>
<br style="FONT: 12px song, Verdana">这个结果正好应证了上面解释，同时，还可是得出一个结论：<br style="FONT: 12px song, Verdana"><span style="LINE-HEIGHT: 19px; COLOR: rgb(255,1,2)">字符串常量，之所以称之为常量，因为它可一看作是一个没有命名的字符串且为常量，存放在静态数据区。</span><br style="FONT: 12px song, Verdana">这里说的静态数据区，是相对于堆、栈等动态数据区而言的。<br style="FONT: 12px song, Verdana">静态数据区存放的是全局变量和静态变量，从这一点上来说，字符串常量又可以称之为一个无名的静态变量，<br style="FONT: 12px song, Verdana">因为"Hello world!"这个字符串在函数 s1和s2 中都引用了，但在内存中却只有一份拷贝，这与静态变量性质相当神似。<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">具体可以参考下面的几篇博文：<br style="FONT: 12px song, Verdana">http://blog.chinaunix.net/u/16292/showart_661593.html<br style="FONT: 12px song, Verdana">http://blog.chinaunix.net/u/16292/showart_664550.html<br style="FONT: 12px song, Verdana">http://blog.chinaunix.net/u/16292/showart_665487.html</span></font></div>
<br><br>转自：<a href="http://zxffl.blog.163.com/blog/static/2590976200931210125220/"><u><font color=#0066cc>http://zxffl.blog.163.com/blog/static/2590976200931210125220/</font></u></a></span></span>
<img src ="http://www.cppblog.com/flyinghare/aggbug/142466.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2011-03-22 12:02 <a href="http://www.cppblog.com/flyinghare/archive/2011/03/22/142466.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>将接口指针赋给某个智能指针对象时，出现 C4800 警告</title><link>http://www.cppblog.com/flyinghare/archive/2011/02/25/140655.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Fri, 25 Feb 2011 08:06:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2011/02/25/140655.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/140655.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2011/02/25/140655.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/140655.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/140655.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;IInternalGameWorldPtr&nbsp;ptrInGameWorld&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;GetGameWorld();&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;C4800</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;ptrInGameWorld</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">InstallLobbyClientHook(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">);</span></div>
<p><br>产生如下错误：<br>1&gt;e:\dgsource\dg_game\project2009\branches\alpha4\dreamgame\client\projects\gameclientshare\gamemoduleui.cpp(47): warning C4800: &#8220;IGameWorld *&#8221;: 将值强制为布尔值&#8220;true&#8221;或&#8220;false&#8221;(性能警告)<br><br>原因：GetGameWorld() 返回的 IGameWorld * 未定义；此前只是做了以下声明:<br></p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #0000ff">interface</span><span style="COLOR: #000000">&nbsp;IGameWorld;</span></div>
<p><br>但未包含 IGameWorld 的头文件。<br><br>在文件开始处增加如下语句，警告消失：</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">..\..\sdk\Include\GameWorld_i.h</span><span style="COLOR: #000000">"</span></div>
<img src ="http://www.cppblog.com/flyinghare/aggbug/140655.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2011-02-25 16:06 <a href="http://www.cppblog.com/flyinghare/archive/2011/02/25/140655.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VS2010 中的 C++ 0x 新特性：Lambdas、auto 和 static_assert</title><link>http://www.cppblog.com/flyinghare/archive/2011/02/18/140244.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Fri, 18 Feb 2011 01:29:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2011/02/18/140244.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/140244.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2011/02/18/140244.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/140244.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/140244.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 转载自痴痴笑笑的博客，略有删改。尽管 C++ 社区对 C++ 0x 很是追捧，但是各厂商对于新标准的支持并不热乎。盼星星盼月亮，微软作为 Windows 平台上最强势的 C++ 编译器厂商也终于在 Visual Studio 2010 中开始支持 C++ 0x 的特性。Visual Studio 2010 中的 Visual C++ 编译器，即 VC10, 包含了 4 个 C++ 0x 的...&nbsp;&nbsp;<a href='http://www.cppblog.com/flyinghare/archive/2011/02/18/140244.html'>阅读全文</a><img src ="http://www.cppblog.com/flyinghare/aggbug/140244.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2011-02-18 09:29 <a href="http://www.cppblog.com/flyinghare/archive/2011/02/18/140244.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>成员函数指针与高性能的C++委托（下篇）</title><link>http://www.cppblog.com/flyinghare/archive/2010/12/15/136456.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Wed, 15 Dec 2010 01:25:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2010/12/15/136456.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/136456.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2010/12/15/136456.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/136456.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/136456.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 撰文：Don Clugston翻译：周翔（接中篇）委托（delegate）和成员函数指针不同，你不难发现委托的用处。最重要的，使用委托可以很容易地实现一个Subject/Observer设计模式的改进版[GoF, p. 293]。Observer（观察者）模式显然在GUI中有很多的应用，但我发现它对应用程序核心的设计也有很大的作用。委托也可用来实现策略（Stra...&nbsp;&nbsp;<a href='http://www.cppblog.com/flyinghare/archive/2010/12/15/136456.html'>阅读全文</a><img src ="http://www.cppblog.com/flyinghare/aggbug/136456.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2010-12-15 09:25 <a href="http://www.cppblog.com/flyinghare/archive/2010/12/15/136456.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>成员函数指针与高性能的C++委托（中篇）</title><link>http://www.cppblog.com/flyinghare/archive/2010/12/15/136455.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Wed, 15 Dec 2010 01:21:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2010/12/15/136455.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/136455.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2010/12/15/136455.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/136455.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/136455.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 撰文：Don Clugston翻译：周翔（接上篇）成员函数指针——为什么那么复杂？类的成员函数和标准的C函数有一些不同。与被显式声明的参数相似，类的成员函数有一个隐藏的参数this，它指向一个类的实例。根据不同的编译器，this或者被看作内部的一个正常的参数，或者会被特别对待（比如，在VC++中，this一般通过ECX寄存器来传递，而普通的成员函数的参数被直接压在堆栈中）。this作为参数和其他普...&nbsp;&nbsp;<a href='http://www.cppblog.com/flyinghare/archive/2010/12/15/136455.html'>阅读全文</a><img src ="http://www.cppblog.com/flyinghare/aggbug/136455.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2010-12-15 09:21 <a href="http://www.cppblog.com/flyinghare/archive/2010/12/15/136455.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>成员函数指针与高性能的C++委托（上篇）</title><link>http://www.cppblog.com/flyinghare/archive/2010/12/15/136453.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Wed, 15 Dec 2010 01:19:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2010/12/15/136453.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/136453.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2010/12/15/136453.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/136453.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/136453.html</trackback:ping><description><![CDATA[<table cellspacing="0" cellpadding="0" width="760" align="center" border="0" style="color: rgb(51, 51, 51); font-family: Tahoma; font-size: 12px; line-height: 18px; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; "><tbody><tr><td align="middle" height="40" style="font-size: 9pt; color: rgb(51, 51, 51); line-height: 18px; font-family: Tahoma; ">撰文：Don Clugston</td></tr></tbody></table><table height="65" cellspacing="0" cellpadding="0" width="760" align="center" border="0" style="color: rgb(51, 51, 51); font-family: Tahoma; font-size: 12px; line-height: 18px; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; "><tbody><tr><td height="65" style="font-size: 9pt; color: rgb(51, 51, 51); line-height: 18px; font-family: Tahoma; "><table width="85%" align="center" border="0"><tbody><tr><td style="font-size: 9pt; color: rgb(51, 51, 51); line-height: 18px; font-family: Tahoma; ">引子<p><br>标准C++中没有真正的面向对象的函数指针。这一点对C++来说是不幸的，因为面向对象的指针（也叫做"闭包（closure）"或"委托（delegate）"）在一些语言中已经证明了它宝贵的价值。在Delphi (Object Pascal)中，面向对象的函数指针是Borland可视化组建库（VCL，Visual Component Library）的基础。而在目前，C#使"委托"的概念日趋流行，这也正显示出C#这种语言的成功。在很多应用程序中，"委托"简化了松耦合对象的设计模式[GoF]。这种特性无疑在标准C++中也会产生很大的作用。</p><p><br>很遗憾，C++中没有"委托"，它只提供了成员函数指针（member function pointers）。很多程序员从没有用过函数指针，这是有特定的原因的。因为函数指针自身有很多奇怪的语法规则（比如"-&gt;*"和".*"操作符），而且很难找到它们的准确含义，并且你会找到更好的办法以避免使用函数指针。更具有讽刺意味的是：事实上，编译器的编写者如果实现"委托"的话会比他费劲地实现成员函数指针要容易地多！</p><p><br>在这篇文章中，我要揭开成员函数指针那"神秘的盖子"。在扼要地重述成员函数指针的语法和特性之后，我会向读者解释成员函数指针在一些常用的编译器中是怎样实现的，然后我会向大家展示编译器怎样有效地实现"委托"。最后我会利用这些精深的知识向你展示在C++编译器上实现优化而可靠的"委托"的技术。比如，在Visual C++(6.0, .NET, and .NET 2003)中对单一目标委托（single-target delegate）的调用，编译器仅仅生成两行汇编代码！</p><p><br>函数指针</p><p><br>下面我们复习一下函数指针。在C和C++语言中，一个命名为my_func_ptr的函数指针指向一个以一个int和一个char*为参数的函数，这个函数返回一个浮点值，声明如下：</p><p><br>float (*my_func_ptr)(int, char *);</p><p>//为了便于理解，我强烈推荐你使用typedef关键字。</p><p>//如果不这样的话，当函数指针作为一个函数的参数传递的时候，</p><p>// 程序会变得晦涩难懂。</p><p>// 这样的话，声明应如下所示：</p><p>typedef float (*MyFuncPtrType)(int, char *);</p><p>MyFuncPtrType my_func_ptr;</p><p><br>应注意，对每一个函数的参数组合，函数指针的类型应该是不同的。在Microsoft Visual C++（以下称MSVC）中，对三种不同的调用方式有不同的类型：__cdecl, __stdcall, 和__fastcall。如果你的函数指针指向一个型如float some_func(int, char *)的函数，这样做就可以了：</p><p><br>my_func_ptr = some_func;</p><p><br>当你想调用它所指向的函数时，你可以这样写：</p><p><br>(*my_func_ptr)(7, "Arbitrary String");</p><p><br>你可以将一种类型的函数指针转换成另一种函数指针类型，但你不可以将一个函数指针指向一个void *型的数据指针。其他的转换操作就不用详叙了。一个函数指针可以被设置为0来表明它是一个空指针。所有的比较运算符（==, !=, &lt;, &gt;, &lt;=, &gt;=）都可以使用，可以使用"==0"或通过一个显式的布尔转换来测试指针是否为空（null）。</p><p><br>在C语言中，函数指针通常用来像qsort一样将函数作为参数，或者作为Windows系统函数的回调函数等等。函数指针还有很多其他的应用。函数指针的实现很简单：它们只是"代码指针（code pointer）"，它们体现在汇编语言中是用来保存子程序代码的首地址。而这种函数指针的存在只是为了保证使用了正确的调用规范。</p><p><br>成员函数指针</p><p><br>在C++程序中，很多函数是成员函数，即这些函数是某个类中的一部分。你不可以像一个普通的函数指针那样指向一个成员函数，正确的做法应该是，你必须使用一个成员函数指针。一个成员函数的指针指向类中的一个成员函数，并和以前有相同的参数，声明如下：</p><p><br>float (SomeClass::*my_memfunc_ptr)(int, char *);</p><p>//对于使用const关键字修饰的成员函数，声明如下：</p><p>float (SomeClass::*my_const_memfunc_ptr)(int, char *) const;</p><p><br>注意使用了特殊的运算符（::*），而"SomeClass"是声明中的一部分。成员函数指针有一个可怕的限制：它们只能指向一个特定的类中的成员函数。对每一种参数的组合，需要有不同的成员函数指针类型，而且对每种使用const修饰的函数和不同类中的函数，也要有不同的函数指针类型。在MSVC中，对下面这四种调用方式都有一种不同的调用类型：__cdecl, __stdcall, __fastcall, 和 __thiscall。（__thiscall是缺省的方式，有趣的是，在任何官方文档中从没有对__thiscall关键字的详细描述，但是它经常在错误信息中出现。如果你显式地使用它，你会看到"它被保留作为以后使用（it is reserved for future use）"的错误提示。）如果你使用了成员函数指针，你最好使用typedef以防止混淆。</p><p><br>将函数指针指向型如float SomeClass::some_member_func(int, char *)的函数，你可以这样写：</p><p><br>my_memfunc_ptr = &amp;SomeClass::some_member_func;</p><p><br>很多编译器（比如MSVC）会让你去掉"&amp;"，而其他一些编译器（比如GNU G++）则需要添加"&amp;"，所以在手写程序的时候我建议把它添上。若要调用成员函数指针，你需要先建立SomeClass的一个实例，并使用特殊操作符"-&gt;*"，这个操作符的优先级较低，你需要将其适当地放入圆括号内。</p><p><br>SomeClass *x = new SomeClass;</p><p>(x-&gt;*my_memfunc_ptr)(6, "Another Arbitrary Parameter");</p><p>//如果类在栈上，你也可以使用".*"运算符。</p><p>SomeClass y;</p><p>(y.*my_memfunc_ptr)(15, "Different parameters this time");</p><p><br>不要怪我使用如此奇怪的语法——看起来C++的设计者对标点符号有着由衷的感情！C++相对于C增加了三种特殊运算符来支持成员指针。"::*"用于指针的声明，而"-&gt;*"和".*"用来调用指针指向的函数。这样看起来对一个语言模糊而又很少使用的部分的过分关注是多余的。（你当然可以重载"-&gt;*"这些运算符，但这不是本文所要涉及的范围。）</p><p><br>一个成员函数指针可以被设置成0，并可以使用"=="和"!="比较运算符，但只能限定在同一个类中的成员函数的指针之间进行这样的比较。任何成员函数指针都可以和0做比较以判断它是否为空。与函数指针不同，不等运算符（&lt;, &gt;, &lt;=, &gt;=）对成员函数指针是不可用的。</p><p><br>成员函数指针的怪异之处</p><p><br>成员函数指针有时表现得很奇怪。首先，你不可以用一个成员函数指针指向一个静态成员函数，你必须使用普通的函数指针才行（在这里"成员函数指针"会产生误解，它实际上应该是"非静态成员函数指针"才对）。其次，当使用类的继承时，会出现一些比较奇怪的情况。比如，下面的代码在MSVC下会编译成功（注意代码注释）：</p><p><br>#include "stdio.h"</p><p>class SomeClass {</p><p>public:</p><p>virtual void some_member_func(int x, char *p) {</p><p>printf("In SomeClass"); };</p><p>};</p><p><br>class DerivedClass : public SomeClass {</p><p>public:</p><p>// 如果你把下一行的注释销掉，带有 line (*)的那一行会出现错误</p><p>// virtual void some_member_func(int x, char *p) { printf("In DerivedClass"); };</p><p>};</p><p><br>int main() {</p><p>//声明SomeClass的成员函数指针</p><p>typedef void (SomeClass::*SomeClassMFP)(int, char *);</p><p>SomeClassMFP my_memfunc_ptr;</p><p>my_memfunc_ptr = &amp;DerivedClass::some_member_func; // ---- line (*)</p><p>return 0;</p><p>}</p><p><br>奇怪的是，&amp;DerivedClass::some_member_func是一个SomeClass类的成员函数指针，而不是DerivedClass类的成员函数指针！（一些编译器稍微有些不同：比如，对于Digital Mars C++，在上面的例子中，&amp;DerivedClass::some_member_func会被认为没有定义。）但是，如果在DerivedClass类中重写（override）了some_member_func函数，代码就无法通过编译，因为现在的&amp;DerivedClass::some_member_func已成为DerivedClass类中的成员函数指针！</p><p><br>成员函数指针之间的类型转换是一个讨论起来非常模糊的话题。在C++的标准化的过程中，在涉及继承的类的成员函数指针时，对于将成员函数指针转化为基类的成员函数指针还是转化为子类成员函数指针的问题和是否可以将一个类的成员函数指针转化为另一个不相关的类的成员函数指针的问题，人们曾有过很激烈的争论。然而不幸的是，在标准委员会做出决定之前，不同的编译器生产商已经根据自己对这些问题的不同的回答实现了自己的编译器。根据标准（第5.2.10/9节），你可以使用reinterpret_cast在一个成员函数指针中保存一个与本来的类不相关的类的成员函数。有关成员函数指针转换的问题的最终结果也没有确定下来。你现在所能做的还是像以前那样——将成员函数指针转化为本类的成员函数的指针。在文章的后面我会继续讨论这个问题，因为这正是各个编译器对这样一个标准没有达成共识的一个话题。</p><p><br>在一些编译器中，在基类和子类的成员函数指针之间的转换时常有怪事发生。当涉及到多重继承时，使用reinterpret_cast将子类转换成基类时，对某一特定编译器来说有可能通过编译，而也有可能通不过编译，这取决于在子类的基类列表中的基类的顺序！下面就是一个例子：</p><p><br>class Derived: public Base1, public Base2 // 情况 (a)</p><p>class Derived2: public Base2, public Base1 // 情况 (b)</p><p>typedef void (Derived::* Derived_mfp)();</p><p>typedef void (Derived2::* Derived2_mfp)();</p><p>typedef void (Base1::* Base1mfp) ();</p><p>typedef void (Base2::* Base2mfp) ();</p><p>Derived_mfp x;</p><p><br>对于情况(a)，static_cast&lt;Base1mfp&gt;(x)是合法的，而static_cast&lt;Base2mfp&gt;(x)则是错误的。然而情况(b)却与之相反。你只可以安全地将子类的成员函数指针转化为第一个基类的成员函数指针！如果你要实验一下，MSVC会发出C4407号警告，而Digital Mars C++会出现编译错误。如果用reinterpret_cast代替static_cast，这两个编译器都会发生错误，但是两种编译器对此有着不同的原因。但是一些编译器对此细节置之不理，大家可要小心了！</p><p><br>标准C++中另一条有趣的规则是：你可以在类定义之前声明它的成员函数指针。这对一些编译器会有一些无法预料的副作用。我待会讨论这个问题，现在你只要知道要尽可能得避免这种情况就是了。</p><p><br>需要值得注意的是，就像成员函数指针，标准C++中同样提供了成员数据指针（member data pointer）。它们具有相同的操作符，而且有一些实现原则也是相同的。它们用在stl::stable_sort的一些实现方案中，而对此很多其他的应用我就不再提及了。</p><p><br>成员函数指针的使用</p><p><br>现在你可能会觉得成员函数指针是有些奇异。但它可以用来做什么呢？对此我在网上做了非常广泛的调查。最后我总结出使用成员函数指针的两点原因：</p><p>&nbsp;</p><p>用来做例子给C++初学者看，帮助它们学习语法；或者</p><p><br>为了实现"委托（delegate）"！</p><p><br>成员函数指针在STL和Boost库的单行函数适配器（one-line function adaptor）中的使用是微不足道的，而且允许你将成员函数和标准算法混合使用。但是它们最重要的应用是在不同类型的应用程序框架中，比如它们形成了MFC消息系统的核心。</p><p><br>当你使用MFC的消息映射宏（比如ON_COMMAND）时，你会组装一个包含消息ID和成员函数指针（型如：CCmdTarget::*成员函数指针）的序列。这是MFC类必须继承CCmdTarget才可以处理消息的原因之一。但是，各种不同的消息处理函数具有不同的参数列表（比如OnDraw处理函数的第一个参数的类型为CDC *），所以序列中必须包含各种不同类型的成员函数指针。MFC是怎样做到这一点的呢？MFC利用了一个可怕的编译器漏洞（hack），它将所有可能出现的成员函数指针放到一个庞大的联合（union）中，从而避免了通常需要进行的C++类型匹配检查。（看一下afximpl.h和cmdtarg.cpp中名为MessageMapFunctions的union，你就会发现这一恐怖的事实。）因为MFC有如此重要的一部分代码，所以事实是，所有的编译器都为这个漏洞开了绿灯。（但是，在后面我们会看到，如果一些类用到了多重继承，这个漏洞在MSVC中就不会起作用，这正是在使用MFC时只能必须使用单一继承的原因。）</p><p><br>在boost::function中有类似的漏洞（但不是太严重）。看起来如果你想做任何有关成员函数指针的比较有趣的事，你就必须做好与这个语言的漏洞进行挑战的准备。要是你想否定C++的成员函数指针设计有缺陷的观点，看来是很难的。</p><p><br>在写这篇文章中，我有一点需要指明："允许成员函数指针之间进行转换（cast），而不允许在转换完成后调用其中的函数"，把这个规则纳入C++的标准中是可笑的。首先，很多流行的编译器对这种转换不支持（所以，转换是标准要求的，但不是可移植的）。其次，所有的编译器，如果转换成功，调用转换后的成员函数指针时仍然可以实现你预期的功能：那编译器就没有所谓的"undefined behavior（未定义的行为）"这类错误出现的必要了（调用（Invocation）是可行的，但这不是标准！）。第三，允许转换而不允许调用是完全没有用处的，只有转换和调用都可行，才能方便而有效地实现委托，从而使这种语言受益。</p><p><br>为了让你确信这一具有争议的论断，考虑一下在一个文件中只有下面的一段代码，这段代码是合法的：</p><p><br>class SomeClass;</p><p><br>typedef void (SomeClass::* SomeClassFunction)(void);</p><p><br>void Invoke(SomeClass *pClass, SomeClassFunction funcptr) {</p><p>(pClass-&gt;*funcptr)(); };</p><p><br>注意到编译器必须生成汇编代码来调用成员函数指针，其实编译器对SomeClass类一无所知。显然，除非链接器进行了一些极端精细的优化措施，否则代码会忽视类的实际定义而能够正确地运行。而这造成的直接后果是，你可以"安全地"调用从完全不同的其他类中转换过来的成员函数指针。</p><p><br>为解释我的断言的另一半——转换并不能按照标准所说的方式进行，我需要在细节上讨论编译器是怎样实现成员函数指针的。我同时会解释为什么使用成员函数指针的规则具有如此严格的限制。获得详细论述成员函数指针的文档不是太容易，并且大家对错误的言论已经习以为常了，所以，我仔细检查了一系列编译器生成的汇编代码......</p><p><br></p><p>转自：<a href="http://dev.csdn.net/htmls/53/53738.html">http://dev.csdn.net/htmls/53/53738.html</a></p></td></tr></tbody></table></td></tr></tbody></table>
<img src ="http://www.cppblog.com/flyinghare/aggbug/136453.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2010-12-15 09:19 <a href="http://www.cppblog.com/flyinghare/archive/2010/12/15/136453.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VS2010 解决方案依赖项设置：会导致lib库目录不起作用</title><link>http://www.cppblog.com/flyinghare/archive/2010/12/08/135816.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Wed, 08 Dec 2010 08:45:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2010/12/08/135816.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/135816.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2010/12/08/135816.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/135816.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/135816.html</trackback:ping><description><![CDATA[当一个解决方案中设置了工程A依赖于工程B；<br>工程B为 lib 静态库；工程A需要链接工程B的库；<br>此时，在该解决方案中编译，工程A和B都不会有问题；
<div style="PADDING-BOTTOM: 32px; BACKGROUND-COLOR: rgb(255,255,255); PADDING-LEFT: 32px; PADDING-RIGHT: 32px; BORDER-LEFT-COLOR: rgb(187,187,187); PADDING-TOP: 32px; background-origin: initial; background-clip: initial">&nbsp;</div>
<div style="PADDING-BOTTOM: 32px; BACKGROUND-COLOR: rgb(255,255,255); PADDING-LEFT: 32px; PADDING-RIGHT: 32px; BORDER-LEFT-COLOR: rgb(187,187,187); PADDING-TOP: 32px; background-origin: initial; background-clip: initial">但是，如果迁移工程A到其他位置，仅附带工程B的头文件和lib文件；并且在工程A中设置了相应的库目录和头文件目录；</div>
<div style="PADDING-BOTTOM: 32px; BACKGROUND-COLOR: rgb(255,255,255); PADDING-LEFT: 32px; PADDING-RIGHT: 32px; BORDER-LEFT-COLOR: rgb(187,187,187); PADDING-TOP: 32px; background-origin: initial; background-clip: initial">但是，编译时，工程A会固执的在当前工程的输出路径中去找工程B的lib文件，导致找不到而报错，例如：</div>
<div style="PADDING-BOTTOM: 32px; BACKGROUND-COLOR: rgb(255,255,255); PADDING-LEFT: 32px; PADDING-RIGHT: 32px; BORDER-LEFT-COLOR: rgb(187,187,187); PADDING-TOP: 32px; background-origin: initial; background-clip: initial">1&gt;LINK : fatal error LNK1104: 无法打开文件&#8220;E:\DGSource\DG_Game\Project2009\trunk\DreamStudio\Projects\Debug\DreamStudioGuidD.lib&#8221;</div>
<div style="PADDING-BOTTOM: 32px; BACKGROUND-COLOR: rgb(255,255,255); PADDING-LEFT: 32px; PADDING-RIGHT: 32px; BORDER-LEFT-COLOR: rgb(187,187,187); PADDING-TOP: 32px; background-origin: initial; background-clip: initial">经检查，发现在解决方案中设置的项目依赖项不是保存在解决方案中的，而是保存在项目文件中的，例如：</div>
<div style="PADDING-BOTTOM: 32px; BACKGROUND-COLOR: rgb(255,255,255); PADDING-LEFT: 32px; PADDING-RIGHT: 32px; BORDER-LEFT-COLOR: rgb(187,187,187); PADDING-TOP: 32px; background-origin: initial; background-clip: initial">
<div style="PADDING-BOTTOM: 32px; BACKGROUND-COLOR: rgb(255,255,255); PADDING-LEFT: 32px; PADDING-RIGHT: 32px; BORDER-LEFT-COLOR: rgb(187,187,187); PADDING-TOP: 32px; background-origin: initial; background-clip: initial">&nbsp;&nbsp;&lt;ItemGroup&gt;</div>
<div style="PADDING-BOTTOM: 32px; BACKGROUND-COLOR: rgb(255,255,255); PADDING-LEFT: 32px; PADDING-RIGHT: 32px; BORDER-LEFT-COLOR: rgb(187,187,187); PADDING-TOP: 32px; background-origin: initial; background-clip: initial">&nbsp;&nbsp; &nbsp;&lt;ProjectReference Include="..\DreamStudioGuid\DreamStudioGuid.vcxproj"&gt;</div>
<div style="PADDING-BOTTOM: 32px; BACKGROUND-COLOR: rgb(255,255,255); PADDING-LEFT: 32px; PADDING-RIGHT: 32px; BORDER-LEFT-COLOR: rgb(187,187,187); PADDING-TOP: 32px; background-origin: initial; background-clip: initial">&nbsp;&nbsp; &nbsp; &nbsp;&lt;Project&gt;{4a2c5657-e601-43ec-8ce5-991c7aec7d10}&lt;/Project&gt;</div>
<div style="PADDING-BOTTOM: 32px; BACKGROUND-COLOR: rgb(255,255,255); PADDING-LEFT: 32px; PADDING-RIGHT: 32px; BORDER-LEFT-COLOR: rgb(187,187,187); PADDING-TOP: 32px; background-origin: initial; background-clip: initial">&nbsp;&nbsp; &nbsp; &nbsp;&lt;ReferenceOutputAssembly&gt;false&lt;/ReferenceOutputAssembly&gt;</div>
<div style="PADDING-BOTTOM: 32px; BACKGROUND-COLOR: rgb(255,255,255); PADDING-LEFT: 32px; PADDING-RIGHT: 32px; BORDER-LEFT-COLOR: rgb(187,187,187); PADDING-TOP: 32px; background-origin: initial; background-clip: initial">&nbsp;&nbsp; &nbsp;&lt;/ProjectReference&gt;</div>
<div style="PADDING-BOTTOM: 32px; BACKGROUND-COLOR: rgb(255,255,255); PADDING-LEFT: 32px; PADDING-RIGHT: 32px; BORDER-LEFT-COLOR: rgb(187,187,187); PADDING-TOP: 32px; background-origin: initial; background-clip: initial">&nbsp;&nbsp; &nbsp;&lt;/ItemGroup&gt;</div>
</div>
<img src ="http://www.cppblog.com/flyinghare/aggbug/135816.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2010-12-08 16:45 <a href="http://www.cppblog.com/flyinghare/archive/2010/12/08/135816.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows异常处理机制介绍</title><link>http://www.cppblog.com/flyinghare/archive/2010/11/04/132421.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Thu, 04 Nov 2010 04:54:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2010/11/04/132421.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/132421.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2010/11/04/132421.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/132421.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/132421.html</trackback:ping><description><![CDATA[<p>最近做了一个Windows下的异常处理模块，查阅了一些新的资料，结合我自己的理解，将一些点滴记录如下，希望对兄弟们有所帮助。</p>
<p><strong><font size=3>一、C++标准异常</font></strong></p>
<p>也就是try、throw、catch这三个关键字。</p>
<p><em>try<br>{<br>&nbsp;&nbsp;&nbsp; &#8230;&#8230;<br>&nbsp;&nbsp;&nbsp; throw &lt;exception-data&gt;<br>&nbsp;&nbsp;&nbsp; &#8230;&#8230;<br>}</em></p>
<p><em>catch (&lt;exception-declaration 1&gt;)<br>{<br>&nbsp;&nbsp;&nbsp; &#8230;&#8230;<br>}<br>catch (&lt;exception-declaration 2&gt;)<br>{<br>&nbsp;&nbsp;&nbsp; &#8230;&#8230;<br>}<br>&#8230;&#8230;</em></p>
<p>try块中的throw会抛出一个数据&lt;exception-data&gt;，比如一个整数，一个字串，或是其他自定义类型的数据。这时，当前程序中止执行，开始查找catch入口。throw抛出的数据类型与catch入口的&lt;exception-declaration&gt;数据类型必须匹配，这一点类似函数调用的形参、实参匹配。一个try块可以对应多个catch块，这一点类似于函数的重载。当然，你也可以用catch (&#8230;)来接收所有可能抛出的数据。MFC提供了一些标准的抛出异常类型，如CFileException类、CDaoException类等，它们都是CException类的派生类，使用MFC时可以了解一下，这里就不多说。</p>
<p>执行完catch块，程序会继续向下执行。</p>
<p>当throw在本函数（或说栈的本帧）没有找到合适的catch块时，会向上一层调用函数（或说栈的上一帧）回溯，直到匹配到合适的try-catch块为止。也就是说，try-catch块可以捕获到try块中调用(可以是多层调用)的函数中的，没被处理的异常。同时，try-catch块是可以嵌套的。</p>
<p>那么，有一个问题：没有try-catch块的，或查找到调用顶层（如main函数）都没有匹配上catch块的throw语句会如何执行呢？这在不同操作系统会有不同的处理，在Windows中则是由一个叫SEH的机制来处理的。</p>
<p><strong><font size=3>二、Windows SEH</font></strong></p>
<p>SEH（Structured Exception Handling），即结构化异常处理，是Microsoft提供的异常处理机制。要了解这个机制，咱先来了解一下__try-__except关键字。</p>
<p><strong>1. __try-__except关键字</strong></p>
<p><em>__try<br>{<br>&nbsp;&nbsp;&nbsp; &#8230;&#8230;<br>}</em></p>
<p><em>__except (&lt;exception&gt;)<br>{<br>&nbsp;&nbsp;&nbsp; &#8230;&#8230;<br>}</em></p>
<p>__try-__except是Microsoft扩展出的C++关键字，__try块中出现错误或异常，一般不再用throw抛出，而是直接产生一个EXCEPTION_POINTERS类型的异常数据，然后开始查找SEH例程入口（调试的情况除外）。首先就会找到与__try块对应的__except块。__except的参数&lt;exception&gt;与catch的参数作用完全不同，也不类似于函数的参数，它主要是用于控制后面的程序执行，为这几个值之一：</p>
<p>EXCEPTION_EXECUTE_HANDLER（1），表示下面执行__except块内及其后面的代码<br>EXCEPTION_CONTINUE_EXECUTION（-1），表示回到抛出异常处继续向下执行<br>EXCEPTION_CONTINUE_SEARCH（0）, 表示查找下一个异常处理例程入口</p>
<p>Microsoft提供两个函数GetExceptionCode(), GetExceptionInformation()，分别可以获取异常号和EXCEPTION_POINTERS类型的异常数据指针。而且这两个函数只能在__except参数&lt;exception&gt;的表达式中使用。为了保证这一点，在Microsoft Visual C++（以下简称VC）中，编译器做了特殊处理，如果这两个函数没有在正确的位置，将产生编译错误。（这个感觉有点搞。）</p>
<p>所以，__except一行一般会这样写：__except (ExceptFilterFunc(GetExceptionInformation()))，其中ExceptFilterFunc是一个自定义的异常处理例程，它输入一个EXCEPTION_POINTERS *类型的参数，返回EXCEPTION_EXECUTE_HANDLER、EXCEPTION_CONTINUE_EXECUTION或EXCEPTION_CONTINUE_SEARCH。</p>
<p>（注：下面所提到的&#8220;异常处理例程&#8221;，不管是自定义的还是系统提供的，都是这种类型的函数，这种函数指针类型在winbase.h中被定义为LPTOP_LEVEL_EXCEPTION_FILTER。）</p>
<p>EXCEPTION_POINTERS结构中包含丰富的异常相关数据，主要有异常号、异常发生时寄存器的值等。</p>
<p>与try-catch一样，__try-__except也支持调用栈回溯，也可以嵌套，但没法重载。</p>
<p>另外，在VC中，还提供__try-__finally块和__leave关键字，这里不细说了，感兴趣的可以查查MSDN。</p>
<p><strong>2. Windows异常处理步骤</strong></p>
<p>回到上文的问题，没有匹配上catch、__except块的错误或异常将会如何处理呢？原来，包括__except块在内，SEH异常处理例程可以有多个，它们的入口地址形成一个链式结构，这个链式结构由Windows操作系统管理。</p>
<p>发生错误或异常后，Windows的处理顺序一般如下：</p>
<p>（1）中止当前程序的执行。</p>
<p>（2）如果程序处于被调试状态，向调试器发送EXCEPTION_DEBUG_EVENT消息。</p>
<p>（3）如果程序没有被调试或者调试器未能处理异常，查找线程相关的异常处理例程（如对应__except块）并处理。如果前面查找到的例程返回EXCEPTION_CONTINUE_SEARCH，且线程有多个异常处理例程，则沿这些例程入口地址组成的链式结构逐一向后查找，请求下一个例程处理。</p>
<p>（4）如果线程没有对应的异常处理例程，或线程所有例程都返回EXCEPTION_CONTINUE_SEARCH，而且程序处于被调试状态，再次通知调试器。</p>
<p>（5）如果程序没有被调试或者调试器仍未处理异常，则进入主线程的&#8220;最终异常处理例程&#8221;链继续查找。</p>
<p>（6）&#8220;最终异常处理例程&#8221;链的最后是Windows默认的系统异常处理程序__CxxUnhandledExceptionFilter()，其处理通常是弹出一个异常对话框，上面显示一些异常信息，提供&#8220;关闭&#8221;、&#8220;调试&#8221;等按钮。</p>
<p>著名的SetUnhandledExceptionFilter()函数就是在所谓&#8220;最终异常处理例程&#8221;链的__CxxUnhandledExceptionFilter()之前插入一个自定义的异常处理例程，当这个例程返回EXCEPTION_EXECUTE_HANDLER时，一般会直接结束进程。</p>
<p><strong><font size=3>三、两种异常处理机制的比较</font></strong></p>
<p>我能想到的一些特征的比较：</p>
<p style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal></p>
<p>
<table style="BORDER-BOTTOM: medium none; BORDER-LEFT: medium none; WIDTH: 464.4pt; BORDER-COLLAPSE: collapse; BORDER-TOP: medium none; BORDER-RIGHT: medium none; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-border-alt: solid windowtext .5pt; mso-yfti-tbllook: 480; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext" class=MsoTableGrid border=1 cellSpacing=0 cellPadding=0 width=619>
    <tbody>
        <tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes">
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: windowtext 1pt solid; PADDING-BOTTOM: 0cm; PADDING-LEFT: 5.4pt; WIDTH: 140.4pt; PADDING-RIGHT: 5.4pt; BACKGROUND: #e6e6e6; BORDER-TOP: windowtext 1pt solid; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt" width=187>
            <p style="TEXT-ALIGN: center; MARGIN: 0cm 0cm 0pt" class=MsoNormal align=center></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; PADDING-LEFT: 5.4pt; WIDTH: 144pt; PADDING-RIGHT: 5.4pt; BACKGROUND: #e6e6e6; BORDER-TOP: windowtext 1pt solid; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt" width=192>
            <p style="TEXT-ALIGN: center; MARGIN: 0cm 0cm 0pt" class=MsoNormal align=center><span><font face="Times New Roman">C++</font></span><span>标准异常</span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; PADDING-LEFT: 5.4pt; WIDTH: 180pt; PADDING-RIGHT: 5.4pt; BACKGROUND: #e6e6e6; BORDER-TOP: windowtext 1pt solid; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt" width=240>
            <p style="TEXT-ALIGN: center; MARGIN: 0cm 0cm 0pt" class=MsoNormal align=center><span><font face="Times New Roman">SEH</font></span></p>
            </td>
        </tr>
        <tr style="mso-yfti-irow: 1">
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: windowtext 1pt solid; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 140.4pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=187>
            <p style="TEXT-ALIGN: center; MARGIN: 0cm 0cm 0pt" class=MsoNormal align=center><span>局部对象析构函数</span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 144pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=192>
            <p style="MARGIN: 0cm 0cm 0pt" class=MsoNormal><span>执行</span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 180pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=240>
            <p style="MARGIN: 0cm 0cm 0pt" class=MsoNormal><span>局部对象有析构函数，且用</span><span><font face="Times New Roman">__try-__exception</font></span><span>时，编译错误</span></p>
            </td>
        </tr>
        <tr style="mso-yfti-irow: 2">
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: windowtext 1pt solid; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 140.4pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=187>
            <p style="TEXT-ALIGN: center; MARGIN: 0cm 0cm 0pt" class=MsoNormal align=center><span>可重载</span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 144pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=192>
            <p style="MARGIN: 0cm 0cm 0pt" class=MsoNormal><span>有参数类型匹配</span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 180pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=240>
            <p style="MARGIN: 0cm 0cm 0pt" class=MsoNormal><span>无条件处理</span></p>
            </td>
        </tr>
        <tr style="mso-yfti-irow: 3">
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: windowtext 1pt solid; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 140.4pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=187>
            <p style="TEXT-ALIGN: center; MARGIN: 0cm 0cm 0pt" class=MsoNormal align=center><span>可移植</span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 144pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=192>
            <p style="MARGIN: 0cm 0cm 0pt" class=MsoNormal><span><font face="Times New Roman">C++</font></span><span>都有，不依赖操作系统平台</span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 180pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=240>
            <p style="MARGIN: 0cm 0cm 0pt" class=MsoNormal><span>只有</span><span><font face="Times New Roman">Windows</font></span><span>提供</span></p>
            </td>
        </tr>
        <tr style="mso-yfti-irow: 4">
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: windowtext 1pt solid; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 140.4pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=187>
            <p style="TEXT-ALIGN: center; MARGIN: 0cm 0cm 0pt" class=MsoNormal align=center><span>程序流程控制</span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 144pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=192>
            <p style="MARGIN: 0cm 0cm 0pt" class=MsoNormal><span><font face="Times New Roman">catch</font></span><span>块后只能继续向下执行</span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 180pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=240>
            <p style="MARGIN: 0cm 0cm 0pt" class=MsoNormal><span><font face="Times New Roman">EXCEPTION_EXECUTE_HANDLER</font></span><span>、</span><span><font face="Times New Roman">EXCEPTION_CONTINUE_EXECUTION</font></span><span>、</span></p>
            <p style="MARGIN: 0cm 0cm 0pt" class=MsoNormal><span><font face="Times New Roman">EXCEPTION_CONTINUE_SEARCH</font></span><span>三种流程控制，多个处理例程的依次处理</span></p>
            </td>
        </tr>
        <tr style="mso-yfti-irow: 5; mso-yfti-lastrow: yes">
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: windowtext 1pt solid; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 140.4pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=187>
            <p style="TEXT-ALIGN: center; MARGIN: 0cm 0cm 0pt" class=MsoNormal align=center><span>数据通用</span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 144pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=192>
            <p style="MARGIN: 0cm 0cm 0pt" class=MsoNormal><span>各种不同的异常数据类型</span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 180pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=240>
            <p style="MARGIN: 0cm 0cm 0pt" class=MsoNormal><span>统一结构的异常数据</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&#160;</p>
<p style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal></p>
<p><strong><font size=3>四、VC编译参数EH</font></strong></p>
<p>在VC中，你可能会发现一个怪异的现象，就是try-catch块无法捕获像&#8220;除0&#8221;、&#8220;空指针访问&#8221;之类的异常。原来，在VC中一般的错误和异常都是用SEH来处理的，不等同于throw抛出的异常。而try-catch对结构化异常的处理，是由编译参数EH来控制的。<span><font face="Times New Roman"> </font></span></p>
<p>
<table style="BORDER-BOTTOM: medium none; BORDER-LEFT: medium none; WIDTH: 464.4pt; BORDER-COLLAPSE: collapse; BORDER-TOP: medium none; BORDER-RIGHT: medium none; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-border-alt: solid windowtext .5pt; mso-yfti-tbllook: 480; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext" class=MsoTableGrid border=1 cellSpacing=0 cellPadding=0 width=619>
    <tbody>
        <tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes">
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: windowtext 1pt solid; PADDING-BOTTOM: 0cm; PADDING-LEFT: 5.4pt; WIDTH: 95.4pt; PADDING-RIGHT: 5.4pt; BACKGROUND: #e6e6e6; BORDER-TOP: windowtext 1pt solid; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt" width=127>
            <p style="TEXT-ALIGN: center; MARGIN: 0cm 0cm 0pt" class=MsoNormal align=center></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; PADDING-LEFT: 5.4pt; WIDTH: 108pt; PADDING-RIGHT: 5.4pt; BACKGROUND: #e6e6e6; BORDER-TOP: windowtext 1pt solid; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt" width=144>
            <p style="TEXT-ALIGN: center; MARGIN: 0cm 0cm 0pt" class=MsoNormal align=center><span>无</span><span><font face="Times New Roman">EH</font></span><span>参数</span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; PADDING-LEFT: 5.4pt; WIDTH: 126pt; PADDING-RIGHT: 5.4pt; BACKGROUND: #e6e6e6; BORDER-TOP: windowtext 1pt solid; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt" width=168>
            <p style="TEXT-ALIGN: center; MARGIN: 0cm 0cm 0pt" class=MsoNormal align=center><span><font face="Times New Roman">EHs(EHsc)</font></span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; PADDING-LEFT: 5.4pt; WIDTH: 135pt; PADDING-RIGHT: 5.4pt; BACKGROUND: #e6e6e6; BORDER-TOP: windowtext 1pt solid; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt" width=180>
            <p style="TEXT-ALIGN: center; MARGIN: 0cm 0cm 0pt" class=MsoNormal align=center><span><font face="Times New Roman">EHa(</font></span><span>同</span><span><font face="Times New Roman">Ehac)</font></span></p>
            </td>
        </tr>
        <tr style="mso-yfti-irow: 1">
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: windowtext 1pt solid; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 95.4pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=127>
            <p style="TEXT-ALIGN: center; MARGIN: 0cm 0cm 0pt" class=MsoNormal align=center><span><font face="Times New Roman">try-catch</font></span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 108pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=144>
            <p style="MARGIN: 0cm 0cm 0pt" class=MsoNormal><span>不处理异常</span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 126pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=168>
            <p style="MARGIN: 0cm 0cm 0pt" class=MsoNormal><span>只处理</span><span><font face="Times New Roman">C++</font></span><span>标准异常，代码优化较好</span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 135pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=180>
            <p style="MARGIN: 0cm 0cm 0pt" class=MsoNormal><span>处理</span><span><font face="Times New Roman">C++</font></span><span>标准异常和结构化异常，代码优化较差</span></p>
            </td>
        </tr>
        <tr style="mso-yfti-irow: 2">
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: windowtext 1pt solid; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 95.4pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=127>
            <p style="TEXT-ALIGN: center; MARGIN: 0cm 0cm 0pt" class=MsoNormal align=center><span><font face="Times New Roman">__try-__except</font></span><span>（</span><span><font face="Times New Roman">VC2005</font></span><span>及以后）</span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 108pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=144>
            <p style="MARGIN: 0cm 0cm 0pt" class=MsoNormal><span>处理</span><span><font face="Times New Roman">C++</font></span><span>标准异常和结构化异常</span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 126pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=168>
            <p style="MARGIN: 0cm 0cm 0pt" class=MsoNormal><span>处理</span><span><font face="Times New Roman">C++</font></span><span>标准异常和结构化异常</span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 135pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=180>
            <p style="MARGIN: 0cm 0cm 0pt" class=MsoNormal><span>处理</span><span><font face="Times New Roman">C++</font></span><span>标准异常和结构化异常</span></p>
            </td>
        </tr>
        <tr style="mso-yfti-irow: 3; mso-yfti-lastrow: yes">
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: windowtext 1pt solid; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 95.4pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=127>
            <p style="TEXT-ALIGN: center; MARGIN: 0cm 0cm 0pt" class=MsoNormal align=center><span><font face="Times New Roman">__try-__except</font></span><span>（</span><span><font face="Times New Roman">VC2003</font></span><span>及以前）</span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 108pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=144>
            <p style="MARGIN: 0cm 0cm 0pt" class=MsoNormal><span>只处理结构化异常</span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 126pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=168>
            <p style="MARGIN: 0cm 0cm 0pt" class=MsoNormal><span>只处理结构化异常</span></p>
            </td>
            <td style="BORDER-BOTTOM: windowtext 1pt solid; BORDER-LEFT: #e0dfe3; PADDING-BOTTOM: 0cm; BACKGROUND-COLOR: transparent; PADDING-LEFT: 5.4pt; WIDTH: 135pt; PADDING-RIGHT: 5.4pt; BORDER-TOP: #e0dfe3; BORDER-RIGHT: windowtext 1pt solid; PADDING-TOP: 0cm; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width=180>
            <p style="MARGIN: 0cm 0cm 0pt" class=MsoNormal><span>只处理结构化异常</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&#160;</p>
<p style="TEXT-INDENT: 21pt; MARGIN: 0cm 0cm 0pt; mso-char-indent-count: 2.0" class=MsoNormal></p>
<p>从表中可以看出，EH参数对__try-__except块的处理并无影响。</p>
<p>从VC2005开始，SEH也可以统一捕获和处理C++标准异常。而在VC2003及之前，C++标准异常只能由catch块来捕获。</p>
<p>VC2005中，EH参数默认为EHsc。</p>
<p>附记：关于自定义SEH异常处例程的编写，如保存内存dump，保存调用栈，使用调试相关的.pdb .map文件等，网上相关的资料很多，需要可以查询。</p>
<br><br>转自：<a href="http://hi.baidu.com/xplot/blog/item/9e7f3154b6e635c2b645ae32.html">http://hi.baidu.com/xplot/blog/item/9e7f3154b6e635c2b645ae32.html</a>
<img src ="http://www.cppblog.com/flyinghare/aggbug/132421.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2010-11-04 12:54 <a href="http://www.cppblog.com/flyinghare/archive/2010/11/04/132421.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VC++动态链接库编程之MFC扩展 DLL</title><link>http://www.cppblog.com/flyinghare/archive/2010/09/30/128131.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Thu, 30 Sep 2010 07:10:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2010/09/30/128131.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/128131.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2010/09/30/128131.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/128131.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/128131.html</trackback:ping><description><![CDATA[下文仅转载了一部分：<br><br>MFC扩展DLL与MFC规则DLL的相同点在于在两种DLL的内部都可以使用MFC类库，其不同点在于MFC扩展DLL与应用程序的接口可以是MFC的。MFC扩展DLL的含义在于它是MFC的扩展，其主要功能是实现从现有MFC库类中派生出可重用的类。MFC扩展DLL使用MFC 动态链接库版本，因此只有用共享MFC 版本生成的MFC 可执行文件（应用程序或规则DLL）才能使用MFC扩展DLL。<br><br>
<div class=guanggao><span id=contentAdv></div>
　　从前文可知，MFC规则DLL被MFC向导自动添加了一个CWinApp的对象，而MFC扩展DLL则不包含该对象，它只是被自动添加了DllMain 函数。对于MFC扩展DLL，开发人员必须在DLL的DllMain函数中添加初始化和结束代码。<br><br>　　从下表我们可以看出三种DLL对DllMain入口函数的不同处理方式：<br><br>
<table border=1 cellSpacing=0 cellPadding=2 width="90%" align=center>
    <tbody>
        <tr>
            <td>DLL类型</td>
            <td>入口函数</td>
        </tr>
        <tr>
            <td>非 MFC DLL</td>
            <td>编程者提供DllMain函数</td>
        </tr>
        <tr>
            <td>MFC规则 DLL</td>
            <td>CWinApp对象的InitInstance 和 ExitInstance</td>
        </tr>
        <tr>
            <td>MFC扩展 DLL</td>
            <td>MFC DLL向导生成DllMain 函数</td>
        </tr>
    </tbody>
</table>
<br>　　对于MFC扩展DLL，系统会自动在工程中添加如下表所示的宏，这些宏为DLL和应用程序的编写提供了方便。像AFX_EXT_CLASS、AFX_EXT_API、AFX_EXT_DATA这样的宏，在DLL和应用程序中将具有不同的定义，这取决于_AFXEXT宏是否被定义。这使得在DLL和应用程序中，使用统一的一个宏就可以表示出输出和输入的不同意思。在DLL中，表示输出（因为_AFXEXT被定义，通常是在编译器的标识参数中指定/D_AFXEXT）；在应用程序中，则表示输入（_AFXEXT没有定义）。<br><br>
<table border=1 cellSpacing=0 cellPadding=2 width="90%" align=center>
    <tbody>
        <tr>
            <td>宏</td>
            <td>定义</td>
        </tr>
        <tr>
            <td>AFX_CLASS_IMPORT</td>
            <td>__declspec(dllexport)</td>
        </tr>
        <tr>
            <td>AFX_API_IMPORT</td>
            <td>__declspec(dllexport)</td>
        </tr>
        <tr>
            <td>AFX_DATA_IMPORT</td>
            <td>__declspec(dllexport)</td>
        </tr>
        <tr>
            <td>AFX_CLASS_EXPORT</td>
            <td>__declspec(dllexport)</td>
        </tr>
        <tr>
            <td>AFX_API_EXPORT</td>
            <td>__declspec(dllexport)</td>
        </tr>
        <tr>
            <td>AFX_DATA_EXPORT</td>
            <td>__declspec(dllexport)</td>
        </tr>
        <tr>
            <td>AFX_EXT_CLASS</td>
            <td>#ifdef _AFXEXT<br>　AFX_CLASS_EXPORT<br>#else<br>　AFX_CLASS_IMPORT</td>
        </tr>
        <tr>
            <td>AFX_EXT_API</td>
            <td>#ifdef _AFXEXT<br>　AFX_API_EXPORT<br>#else<br>　AFX_API_IMPORT</td>
        </tr>
        <tr>
            <td>AFX_EXT_DATA</td>
            <td>#ifdef _AFXEXT<br>　AFX_DATA_EXPORT<br>#else<br>　AFX_DATA_IMPORT</td>
        </tr>
    </tbody>
</table>
<br><br>转自：<a href="http://peirenlei.javaeye.com/blog/305113">http://peirenlei.javaeye.com/blog/305113</a></span>
<img src ="http://www.cppblog.com/flyinghare/aggbug/128131.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2010-09-30 15:10 <a href="http://www.cppblog.com/flyinghare/archive/2010/09/30/128131.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用VC调试程序时，打开异常中断。哪出问题就会自动定位了</title><link>http://www.cppblog.com/flyinghare/archive/2010/09/29/128069.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Wed, 29 Sep 2010 09:26:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2010/09/29/128069.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/128069.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2010/09/29/128069.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/128069.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/128069.html</trackback:ping><description><![CDATA[<table cellSpacing=0 cellPadding=0 done0="0">
    <tbody done0="0">
        <tr done0="0">
            <td style="FILTER: ; ZOOM: 1; DISPLAY: block; VISIBILITY: visible" id=postmessage_49614 class=t_msgfont jQuery1285751456617="3">
            <p>from devdiv.net<br><br>打开VC工程后，菜单：Debug--&gt;exceptions</p>
            <p><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/flyinghare/125_1245057344ErHe.jpg" width=355 height=323><br><br>然后选择需要中断的异常<br><img border=0 src="http://www.cppblog.com/images/cppblog_com/flyinghare/125_1245057348UJUz.jpg" width=601 height=311><br><br>程序异常（这里以除0为例）<br>IDE自动断在错误代码处：<br><img border=0 src="http://www.cppblog.com/images/cppblog_com/flyinghare/125_1245057780ny6G.jpg" width=877 height=402></p>
            </td>
        </tr>
    </tbody>
</table>
<div id=relatedtags>转自：<a href="http://www.devdiv.net/bbs/viewthread.php?tid=10287&amp;rpid=51710&amp;ordertype=0&amp;page=1#pid51710">http://www.devdiv.net/bbs/viewthread.php?tid=10287&amp;rpid=51710&amp;ordertype=0&amp;page=1#pid51710</a></div>
<script type=text/javascript src="tag.php?action=relatetag&amp;rtid=10287" reload="1"></script>
<img src ="http://www.cppblog.com/flyinghare/aggbug/128069.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2010-09-29 17:26 <a href="http://www.cppblog.com/flyinghare/archive/2010/09/29/128069.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>autoexp.dat入门（调试时自定义变量显示）</title><link>http://www.cppblog.com/flyinghare/archive/2010/09/27/127836.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Mon, 27 Sep 2010 00:21:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2010/09/27/127836.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/127836.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2010/09/27/127836.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/127836.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/127836.html</trackback:ping><description><![CDATA[VC在调试状态下，会以三种方式显示一个变量的内容，分别是<strong>preview</strong>, <strong>children</strong>和<strong>stringview</strong>，例如下图所示，定义一个std::string类型的变量，鼠标悬停后显示的内容就是preview，children是点击&#8221;+&#8221;符号后显示的内容，而对于含有字符串内容的变量，点击上放大镜符号，会弹出单独的窗口内显示其中的字符串内容。<br>&nbsp;
<p><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/flyinghare/autoexp-3.gif" width=533 height=213><br>&nbsp;&nbsp;&nbsp;&nbsp;针对这部分功能，微软提供给开发者一个自定义接口，就是通过修改autoexp.dat这个看起来其貌不扬的小文件，该文件放在&#8220;$(VSINSTALLDIR)\Common7\Packages\Debugger&#8221;目录下，微软并没有提供关于这个文件的说明文档，只是在这个文件开始的地方有一些简单的说明，好在这个文件的结构并不复杂，通过分析现成的例子，大概也能了解个八九不离十。<br>&nbsp;&nbsp;&nbsp;&nbsp;先以一个例子说明如何使用这个文件，打开这个文件，在&#8221;[Visualizer]&#8220;这一行下面添加下面的内容</p>
<div class=hl-surround>
<div class=hl-main><span style="COLOR: blue">MyClass</span><span style="COLOR: olive">{</span><span style="COLOR: gray"><br>&nbsp;&nbsp; &nbsp;</span><span style="COLOR: blue">preview</span><span style="COLOR: gray"> <br>&nbsp;&nbsp; &nbsp;</span><span style="COLOR: olive">(</span><span style="COLOR: gray"><br>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;#</span><span style="COLOR: olive">(</span><span style="COLOR: gray"><br>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span style="COLOR: #8b0000">"</span><span style="COLOR: red">Hello,World!</span><span style="COLOR: #8b0000">"</span><span style="COLOR: gray"><br>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</span><span style="COLOR: olive">)</span><span style="COLOR: gray"><br>&nbsp;&nbsp; &nbsp;</span><span style="COLOR: olive">)</span><span style="COLOR: gray"><br></span><span style="COLOR: olive">}</span></div>
</div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;然后启动VC, 随便定义一个名字为MyClass的类，当使用VC的调试器查看这个类的内容时，你会发现显示的调试内容已经变成了&#8221;Hello,World!&#8221;<br><img border=0 src="http://www.cppblog.com/images/cppblog_com/flyinghare/autoexp-1.gif" width=310 height=174><br><span id=more-924></span><br>&nbsp;&nbsp;&nbsp;&nbsp;下面我们再来看一个稍微复杂的例子，比如一个自定义的数组类</p>
<div class=hl-surround>
<div class=hl-main><span class=hl-types>struct</span><span style="COLOR: gray"> </span><span style="COLOR: blue">MyClass</span><span style="COLOR: gray"><br></span><span style="COLOR: olive">{</span><span style="COLOR: gray"><br>&nbsp;&nbsp; &nbsp;</span><span class=hl-types>int</span><span style="COLOR: gray"> </span><span style="COLOR: blue">size</span><span style="COLOR: olive">[</span><span style="COLOR: maroon">32</span><span style="COLOR: olive">]</span><span style="COLOR: gray">;<br>&nbsp;&nbsp; &nbsp;</span><span class=hl-types>int</span><span style="COLOR: gray">* </span><span style="COLOR: blue">buf</span><span style="COLOR: gray">;<br></span><span style="COLOR: olive">}</span><span style="COLOR: gray">;</span></div>
</div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;调试这个数据结构的时候，我们想显示这个数组的元素个数，每个元素的值，以及每个元素的奇偶性，那么需要这样定义:</p>
<div class=hl-surround>
<div class=hl-main><span style="COLOR: blue">MyClass</span><span style="COLOR: olive">{</span><span style="COLOR: gray"><br>&nbsp;</span><span style="COLOR: blue">preview</span><span style="COLOR: gray"><br>&nbsp;</span><span style="COLOR: olive">(</span><span style="COLOR: gray"><br>&nbsp; #</span><span style="COLOR: olive">(</span><span style="COLOR: gray"><br>&nbsp;&nbsp; </span><span style="COLOR: #8b0000">"</span><span style="COLOR: red">[count is </span><span style="COLOR: #8b0000">"</span><span style="COLOR: gray">, $</span><span style="COLOR: blue">c</span><span style="COLOR: gray">.</span><span style="COLOR: blue">size</span><span style="COLOR: gray">, </span><span style="COLOR: #8b0000">"</span><span style="COLOR: red">] </span><span style="COLOR: #8b0000">"</span><span style="COLOR: gray">,<br>&nbsp;&nbsp; </span><span style="COLOR: #8b0000">"</span><span style="COLOR: red">(buf </span><span style="COLOR: #8b0000">"</span><span style="COLOR: gray">, <br></span><span class=hl-prepro>&nbsp; &nbsp; #array</span><span style="COLOR: gray"><br>&nbsp;&nbsp; &nbsp;</span><span style="COLOR: olive">(</span><span style="COLOR: gray"> <br>&nbsp;&nbsp; &nbsp; </span><span style="COLOR: blue">expr</span><span style="COLOR: gray">: $</span><span style="COLOR: blue">c</span><span style="COLOR: gray">.</span><span style="COLOR: blue">buf</span><span style="COLOR: olive">[</span><span style="COLOR: gray">$</span><span style="COLOR: blue">i</span><span style="COLOR: olive">]</span><span style="COLOR: gray">, <br>&nbsp;&nbsp; &nbsp; </span><span style="COLOR: blue">size</span><span style="COLOR: gray">: $</span><span style="COLOR: blue">c</span><span style="COLOR: gray">.</span><span style="COLOR: blue">size</span><span style="COLOR: gray"><br>&nbsp;&nbsp; &nbsp;</span><span style="COLOR: olive">)</span><span style="COLOR: gray">: $</span><span style="COLOR: blue">e</span><span style="COLOR: gray">, <br>&nbsp;&nbsp; </span><span style="COLOR: #8b0000">"</span><span style="COLOR: red">) </span><span style="COLOR: #8b0000">"</span><span style="COLOR: gray">,<br>&nbsp;&nbsp; </span><span style="COLOR: #8b0000">"</span><span style="COLOR: red">(odd </span><span style="COLOR: #8b0000">"</span><span style="COLOR: gray">, <br></span><span class=hl-prepro>&nbsp; &nbsp;#array</span><span style="COLOR: gray"><br>&nbsp;&nbsp; </span><span style="COLOR: olive">(</span><span style="COLOR: gray"> <br>&nbsp;&nbsp; &nbsp;</span><span style="COLOR: blue">expr</span><span style="COLOR: gray">: $</span><span style="COLOR: blue">c</span><span style="COLOR: gray">.</span><span style="COLOR: blue">buf</span><span style="COLOR: olive">[</span><span style="COLOR: gray">$</span><span style="COLOR: blue">i</span><span style="COLOR: olive">]</span><span style="COLOR: gray">, <br>&nbsp;&nbsp; &nbsp;</span><span style="COLOR: blue">size</span><span style="COLOR: gray">: $</span><span style="COLOR: blue">c</span><span style="COLOR: gray">.</span><span style="COLOR: blue">size</span><span style="COLOR: gray"><br>&nbsp;&nbsp; </span><span style="COLOR: olive">)</span><span style="COLOR: gray"> : $</span><span style="COLOR: blue">e</span><span style="COLOR: gray">&amp;</span><span style="COLOR: maroon">1</span><span style="COLOR: gray">, <br>&nbsp;&nbsp; </span><span style="COLOR: #8b0000">"</span><span style="COLOR: red">)</span><span style="COLOR: #8b0000">"</span><span style="COLOR: gray"><br>&nbsp; </span><span style="COLOR: olive">)</span><span style="COLOR: gray"><br>&nbsp;</span><span style="COLOR: olive">)</span><span style="COLOR: gray"><br></span><span style="COLOR: olive">}</span></div>
</div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;实际显示效果为:<br><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/flyinghare/autoexp-31.gif" width=347 height=275><br>&nbsp;&nbsp;&nbsp;&nbsp;其中，<strong>$c</strong>表示当前所定义数据结构，<strong>#array</strong>表示用数组形式显示内容，<strong>$i</strong>表示数组中的每个元素的索引，<strong>$e</strong>表示每个元素的值，同样，可以用#tree和#list分别用来显示树形数据结构和链表类型的数据结构。<br>&nbsp;&nbsp;&nbsp;&nbsp;autoexp.dat中已经对VC提供的缺省的STL数据结构做了定义，比如vector,map等，通过分析这些定义，还可以挖出很多有趣的功能，比如用#if/#else/#switch/#case等条件判断功能，在处理一些比较复杂的组合类型的数据结构时，就非常有用。<br>&nbsp;&nbsp;&nbsp;&nbsp;下面是一份我制作的，针对另一份较为常用的STL库<a href="http://www.stlport.org/index.html"><u><font color=#0066cc>STLPORT</font></u></a> 中部分数据结构的定义，适应STLPORT 5.2版本，使用方法是将其中的内容拷贝到autoexp.dat的&#8221;[Visualizer]&#8220;段中，大家有兴趣的话可以拿去使用，如果发现错误或者有补充的话，请通知我。</p>
<p>下载: <strong><a href="http://www.thecodeway.com/blog/wp-content/uploads/2010/06/autoexp.zip"><u><font color=#0066cc>autoexp.dat</font></u></a></strong> (1.2K)<br><br>转自：<a href="http://www.thecodeway.com/blog/?p=924#more-924">http://www.thecodeway.com/blog/?p=924#more-924</a></p>
<img src ="http://www.cppblog.com/flyinghare/aggbug/127836.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2010-09-27 08:21 <a href="http://www.cppblog.com/flyinghare/archive/2010/09/27/127836.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>float和double类型的内存分布和比较方法</title><link>http://www.cppblog.com/flyinghare/archive/2010/08/27/124935.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Fri, 27 Aug 2010 05:31:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2010/08/27/124935.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/124935.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2010/08/27/124935.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/124935.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/124935.html</trackback:ping><description><![CDATA[<p>C/C++的浮点数据类型有float和double两种。<br>类型float大小为4字节，即32位，内存中的存储方式如下：<br>&nbsp;符号位（1 bit） 指数（8 bit） 尾数（23 bit） </p>
<p><br>类型double大小为8字节，即64位，内存布局如下：<br>符号位（1 bit） 指数（11 bit） 尾数（52 bit） </p>
<p><br>&nbsp;<br>符号位决定浮点数的正负，0正1负。<br>指数和尾数均从浮点数的二进制科学计数形式中获取。<br>如，十进制浮点数2.5的二进制形式为10.1，转换为科学计数法形式为(1.01)*(10^1)，由此可知指数为1，尾数（即科学计数法的小数部分）为01。<br>根据浮点数的存储标准（IEEE制定），float类型指数的起始数为127（二进制0111 1111），double类型指数的起始数为1023(二进制011 1111 1111)，在此基础上加指数，得到的就是内存中指数的表示形式。尾数则直接填入，如果空间多余则以0补齐，如果空间不够则0舍1入。所以float和double类型分别表示的2.5如下（二进制）：<br>符号位 指数 尾数 <br>0 1000 0000 010 0000 0000 0000 0000 0000 <br>0 100 0000 0000 0100 0000 0000 0000 0000 0000 0000 <br>0000 0000 0000 0000 0000 0000 </p>
<p><br>浮点数2.5可以用二进制小数准确表示（2.5=1*(2^1)+0*(2^0)+1*(2^-1)），但很多小数不可以准确表示，其二进制形式的小数部分会无限循环，如浮点数-1.2表示如下（二进制）：<br>符号位 指数 尾数 <br>1 0111 1111 0011 0011 0011 0011 0011 010 <br>1 011 1111 1111 0011 0011 0011 0011 0011 0011 0011<br>0011 0011 0011 0011 0011 0011 </p>
<p><br>由于对无限循环尾数的截取遵循0舍1入，尾数的第21~24位为0011，第53~56位为0011，而float尾数容量为23位，double尾数容量为52位，所以，float形式的最后三位因进位而成010，double形式则没有进位发生。<br>&nbsp;<br>类型float和double通过==,&gt;,&lt;等比较不会引起编译错误，但是非常可能得到错误的结果。这是因为它们的内存分布不同，不可以直接比较。正确的方法是转换为同一类型后比较两者差值，如果结果小于规定的小值，则视为相等。<br>如，一个比较double的实现：<br><a href="http://metasharp.net/index.php?title=How_to_compare_double_or_float_in_Cpp">http://metasharp.net/index.php?title=How_to_compare_double_or_float_in_Cpp</a><br>另外，本文参考了如下webs：<br><a href="http://cdatatype.blogspot.com/2008/01/memory-map-of-floatdouble.html">http://cdatatype.blogspot.com/2008/01/memory-map-of-floatdouble.html</a><br><a href="http://blog.csdn.net/hzb1983/archive/2007/09/24/1798555.aspx">http://blog.csdn.net/hzb1983/archive/2007/09/24/1798555.aspx</a><br>&nbsp;<br>P.S.<br>1)<br>IEEE浮点数标准：&nbsp;&nbsp;&nbsp;&nbsp; 4字节浮点数：1位符号位，8位阶数（基数为127的移码），23位尾数；&nbsp;&nbsp;&nbsp;&nbsp; 8字节浮点数：1位符号位，11位阶数（基数为1023的移码），52位尾数<br>2 )<br>在VC中： float数值范围约在 -10e38~10e38，并提供7位有效数字位，绝对值小于10e38地数被处理成零值 double数值范围约在-10e308~10e308，并提供15~16位有效数字，绝对值小于10e308地数被处理成零值</p>
<p><br>本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/vinsendai/archive/2008/06/27/2593035.aspx">http://blog.csdn.net/vinsendai/archive/2008/06/27/2593035.aspx</a></p>
<img src ="http://www.cppblog.com/flyinghare/aggbug/124935.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2010-08-27 13:31 <a href="http://www.cppblog.com/flyinghare/archive/2010/08/27/124935.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用经典方式察看VS2010中MSDN</title><link>http://www.cppblog.com/flyinghare/archive/2010/08/02/122005.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Mon, 02 Aug 2010 13:39:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2010/08/02/122005.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/122005.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2010/08/02/122005.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/122005.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/122005.html</trackback:ping><description><![CDATA[<a href="http://visualstudiogallery.msdn.microsoft.com/zh-cn/4c360395-6afd-4087-94ed-cbcbebe04a20?SRC=Home">http://visualstudiogallery.msdn.microsoft.com/zh-cn/4c360395-6afd-4087-94ed-cbcbebe04a20?SRC=Home</a><br><br><font size=4>H3Viewer&nbsp;by&nbsp;</font><a href="http://helpware.net/" rel=nofollow target=_blank><font color=#0d76c2 size=4>The Helpware Group</font></a>
<p><span style="FONT-FAMILY: verdana,geneva">Replace the VS 2010 help viewer or run stand-alone. The viewer is free for personal use. Contact us if you need to distribute it.</span></p>
<p><span style="FONT-FAMILY: verdana,geneva">See the <a href="http://mshcmigrate.helpmvp.com/viewer" target=_blank><font color=#0d76c2>H3Viewer Home Page&nbsp;</font></a></span></p>
<p><span style="FONT-FAMILY: verdana,geneva">Features:</span></p>
<ul>
    <li><span style="FONT-FAMILY: verdana,geneva">Similar experience to VS 2005\2008 DExplore.</span>
    <li><span style="FONT-FAMILY: verdana,geneva">Full TOC with TOC Sync.</span>
    <li><span style="FONT-FAMILY: verdana,geneva">Full Index. Two modes: Both VS 2010 and DExplore type experience.</span>
    <li><span style="FONT-FAMILY: verdana,geneva">Text-to-Speech reader.</span>
    <li><span style="FONT-FAMILY: verdana,geneva">Full bookmark support.</span>
    <li><span style="FONT-FAMILY: verdana,geneva">Set default viewer for VS 2010.</span>
    <li><span style="FONT-FAMILY: verdana,geneva">Option: Open F1 help in a new page tab.</span>
    <li><span style="FONT-FAMILY: verdana,geneva">View different MSDN language catalogs.</span>
    <li><span style="FONT-FAMILY: verdana,geneva">UI Translations available (see below).</span>
    <li><span style="FONT-FAMILY: verdana,geneva">Direct link to equivalent MSDN online page.</span>
    <li><span style="FONT-FAMILY: verdana,geneva">Open current page in selected browser.</span>
    <li><span style="FONT-FAMILY: verdana,geneva">etc.</span> </li>
</ul>
<p>Build 54 adds Czeck &amp; Swedish to the GUI Language packs</p>
<ul>
    <li>Czech -- Translated by&nbsp;Martin &#352;ojdr,&nbsp;www.sojdr.com
    <li>German -- Translated by&nbsp;Ulrich Kulle [MVP 2007-2009], www.help-info.de
    <li>Hebrew -- Translated by Ishai Sagi [MVP],<span>&nbsp;www.sharepoint-tips.com</span>
    <li>Italian&nbsp;-- Translated&nbsp;by Alessandro Del Sole [MVP], www.visual-basic.it
    <li>Japanese - Translated by&nbsp;Tomohiro Takano
    <li>Polish -- Translated by Piotr Strycharz, www.computerplus.pl
    <li>Simplified Chinese -- Translated by Hu Hsiaotao
    <li>Swedish -- Translated by&nbsp;Tobias Moberg,&nbsp;www.carmenta.com </li>
</ul>
<ul>
    <li>Don't see your language? <a href="http://mshcmigrate.helpmvp.com/viewer/lang" target=_blank><font color=#0d76c2>Help us translate. It's easy</font></a>. </li>
</ul>
<p>Note to user Nofb: I've also added a check for "MS Help Viewer Power Toy Beta" as requested. In future I'd prefer you contact me directly or use Q &amp; A section. Writing complaints in the review tab is a one way conversation. I could have quickly told you that there was a known problem with the MS Beta and to check the online documentation. Thanks!</p>
<p>&nbsp;</p>
<h3>Known Issues</h3>
<ul>
    <li>Application Freezes<br>The embedded browser is Internet Explorer. On some systems after a few successful clicks the application seems to hang. Try clearing the IE cache, resetting IE settings, and removing 3rd-party IE add-ons you don't use. (all I can say is bring on IE9)
    <li>Pages without style &amp; broken links&nbsp;<br>If you find pages are not showing style correctly and some links are not working then it probably means you have the&nbsp;<a href="http://mshcmigrate.helpmvp.com/news/newhelpviewerpowertoolbeta"><font color=#0d76c2>Help Viewer power toy</font></a>&nbsp;Beta installed. Uninstall this and it will immediately return to normal. Also remember to stop the Agent tray application. </li>
</ul>
<p>&nbsp;</p>
<h2><span style="FONT-FAMILY: verdana,geneva">Screen Shots</span></h2>
<p><span style="FONT-FAMILY: verdana,geneva">Notice the pink folder, which is an orphan help branch not attached to the main VS 2010 TOC. The TOC Sync command will add orphans if found.</span></p>
<p><img alt="" src="http://visualstudiogallery.msdn.microsoft.com/en-us/site/view/file/31748/0/h3Viewer001.png" width=802 height=547></p>
<p>&nbsp;</p>
<p><span style="FONT-FAMILY: verdana,geneva">Inline Index disambiguator. Load full Index (VS 2008 style) or partial load as you type index (VS 2010 style).</span></p>
<p><span style="FONT-FAMILY: verdana,geneva"><img alt="" src="http://i1.visualstudiogallery.msdn.microsoft.com/en-us/4c360395-6afd-4087-94ed-cbcbebe04a20/image/file/31754/0/h3viewer002.png" width=802 height=546><br></span></p>
<p>&nbsp;</p>
<p>Full bookmark support for Help Viewer URLs.</p>
<p><img alt="" src="http://i1.visualstudiogallery.msdn.microsoft.com/en-us/4c360395-6afd-4087-94ed-cbcbebe04a20/image/file/31755/0/h3viewer003.png" width=802 height=546></p>
<p>&nbsp;</p>
<p><span style="FONT-FAMILY: verdana,geneva">Here we've downloaded Russian help (vs\100\ru) using&nbsp;<a href="http://vshelpdownloader.codeplex.com/" rel=nofollow target=_blank><font color=#0d76c2>VSHelpDownloader</font></a>. Press F1 in VS 2010 to display the topic in whatever language is loaded.<br></span></p>
<p><span style="FONT-FAMILY: verdana,geneva"><img alt="" src="http://i2.visualstudiogallery.msdn.microsoft.com/en-us/4c360395-6afd-4087-94ed-cbcbebe04a20/image/file/31839/0/h3viewerrussion.png" width=864 height=735><br></span></p>
<img src ="http://www.cppblog.com/flyinghare/aggbug/122005.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2010-08-02 21:39 <a href="http://www.cppblog.com/flyinghare/archive/2010/08/02/122005.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>