﻿<?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/SpringSnow/category/8493.html</link><description>雪化了，花开了，春天来了</description><language>zh-cn</language><lastBuildDate>Tue, 22 Sep 2009 08:08:48 GMT</lastBuildDate><pubDate>Tue, 22 Sep 2009 08:08:48 GMT</pubDate><ttl>60</ttl><item><title>c++学习——More Effective C++ 基础议题三</title><link>http://www.cppblog.com/SpringSnow/archive/2009/09/22/96936.html</link><dc:creator>Sandy</dc:creator><author>Sandy</author><pubDate>Tue, 22 Sep 2009 05:33:00 GMT</pubDate><guid>http://www.cppblog.com/SpringSnow/archive/2009/09/22/96936.html</guid><wfw:comment>http://www.cppblog.com/SpringSnow/comments/96936.html</wfw:comment><comments>http://www.cppblog.com/SpringSnow/archive/2009/09/22/96936.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/SpringSnow/comments/commentRss/96936.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/SpringSnow/services/trackbacks/96936.html</trackback:ping><description><![CDATA[条款四 避免不必要的默认构造函数<br><br>默认构造函数（指没有参数的构造函数）是指C++语言中，你不用传参数就可以调用的构造函数。构造函数用于初始化对象，而默认构造函数可以在不依赖任何外部信息的情况下创建对象。<br><br>在一个完美的世界里，无需任何外部信息即可创建对象的类可以包含默认构造函数，而需要额外信息来创建对象的类则不包含默认构造函数。可是我们的世界是不完美的，所以我们必将一些额外的因素考虑在内。特别地，如果一个类没有默认构造函数，使用这个类的时候就会有一些限制。<br><br>没有默认构造函数，在三种情况下它的应用可能会出现问题：<br>第一个问题是创建数组的时候，通常没有很好的办法可以指定数组元素的构造函数的参数。<br>第二个问题是没有默认构造函数的类他们无法作为许多基于模板的容器类的类型参数使用。因为通常用于实例化模板的哪些类型需要提供默认构造函数。<br>第三个问题是在有虚基类的时候应该提供默认构造函数还是不提供默认构造函数。没有默认构造函数的虚基类使用起来很痛苦，这是因为虚基类的构造函数所要求的参数必须由创建对象所属的最远的派生类所提供。<br><br>正因为这些强加于没有默认构造函数的类上的重中限制，一些人认为所有的类都应该有默认构造函数，即使默认构造函数没有足够的信息来完全初始化一个对象。<br><br>但是默认构造函数会影响类的运行效率，有时会使其他成员函数变得复杂。<br><br>如果一个类的构造函数能够确保所有的数据成员被正确初始化，就能避免付出一些代价。通常默认构造函数不提供这些保证。如果默认构造函数对于某些类没有太大意义，最好避免使用他们。这给使用这种类加了一些限制，但是当你使用它时，它可以向你保证你能很放心地相信这个类被正确得初始化，并且具有高效的效率。<br><br>说实话，这一章节我看得不是很明白。<br>作者在一开始，列举了一些没有默认构造函数我们可能遇到的问题，在这些问题下，进而得出默认构造函数所带来的一些效率和代价困扰。看来还需要在实践中仔细揣摩揣摩。<br><br><br><br>
<img src ="http://www.cppblog.com/SpringSnow/aggbug/96936.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/SpringSnow/" target="_blank">Sandy</a> 2009-09-22 13:33 <a href="http://www.cppblog.com/SpringSnow/archive/2009/09/22/96936.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++学习——More Effective C++ 基础议题二</title><link>http://www.cppblog.com/SpringSnow/archive/2009/09/22/96922.html</link><dc:creator>Sandy</dc:creator><author>Sandy</author><pubDate>Tue, 22 Sep 2009 03:57:00 GMT</pubDate><guid>http://www.cppblog.com/SpringSnow/archive/2009/09/22/96922.html</guid><wfw:comment>http://www.cppblog.com/SpringSnow/comments/96922.html</wfw:comment><comments>http://www.cppblog.com/SpringSnow/archive/2009/09/22/96922.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/SpringSnow/comments/commentRss/96922.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/SpringSnow/services/trackbacks/96922.html</trackback:ping><description><![CDATA[<p>条款三 绝不要把多态应用于数组<br><br>继承的一大特性是，允许你通过指向基类的指针和引用来操纵派生类对象。也允许通过基类指针和引用来操纵派生类数组。<br><br>但是用基类指针操纵一个包含派生类对象的数组，就会发生各种个样的问题，其结果往往是不确定的。<br><br>我根据书中的例子，写了一个小程序：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;BST<br><img id=Codehighlighter1_53_93_Open_Image onclick="this.style.display='none'; Codehighlighter1_53_93_Open_Text.style.display='none'; Codehighlighter1_53_93_Closed_Image.style.display='inline'; Codehighlighter1_53_93_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_53_93_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_53_93_Closed_Text.style.display='none'; Codehighlighter1_53_93_Open_Image.style.display='inline'; Codehighlighter1_53_93_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_53_93_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_53_93_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;BST()<br><img id=Codehighlighter1_71_83_Open_Image onclick="this.style.display='none'; Codehighlighter1_71_83_Open_Text.style.display='none'; Codehighlighter1_71_83_Closed_Image.style.display='inline'; Codehighlighter1_71_83_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_71_83_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_71_83_Closed_Text.style.display='none'; Codehighlighter1_71_83_Open_Image.style.display='inline'; Codehighlighter1_71_83_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_71_83_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_71_83_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;BalancedBST:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;BST<br><img id=Codehighlighter1_127_146_Open_Image onclick="this.style.display='none'; Codehighlighter1_127_146_Open_Text.style.display='none'; Codehighlighter1_127_146_Closed_Image.style.display='inline'; Codehighlighter1_127_146_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_127_146_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_127_146_Closed_Text.style.display='none'; Codehighlighter1_127_146_Open_Image.style.display='inline'; Codehighlighter1_127_146_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_127_146_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_127_146_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;j;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;printBSTArray(ostream</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">out</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;BST&nbsp;arr[],&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;numElements)<br><img id=Codehighlighter1_217_291_Open_Image onclick="this.style.display='none'; Codehighlighter1_217_291_Open_Text.style.display='none'; Codehighlighter1_217_291_Closed_Image.style.display='inline'; Codehighlighter1_217_291_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_217_291_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_217_291_Closed_Text.style.display='none'; Codehighlighter1_217_291_Open_Image.style.display='inline'; Codehighlighter1_217_291_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_217_291_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_217_291_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;numElements;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_259_289_Open_Image onclick="this.style.display='none'; Codehighlighter1_259_289_Open_Text.style.display='none'; Codehighlighter1_259_289_Closed_Image.style.display='inline'; Codehighlighter1_259_289_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_259_289_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_259_289_Closed_Text.style.display='none'; Codehighlighter1_259_289_Open_Image.style.display='inline'; Codehighlighter1_259_289_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_259_289_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_259_289_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">out</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;arr[i].i&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br><img id=Codehighlighter1_305_513_Open_Image onclick="this.style.display='none'; Codehighlighter1_305_513_Open_Text.style.display='none'; Codehighlighter1_305_513_Closed_Image.style.display='inline'; Codehighlighter1_305_513_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_305_513_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_305_513_Closed_Text.style.display='none'; Codehighlighter1_305_513_Open_Image.style.display='inline'; Codehighlighter1_305_513_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_305_513_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_305_513_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">BST<img src="http://www.cppblog.com/Images/dot.gif">.\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;BST&nbsp;BSTArray[</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;printBSTArray(cout,&nbsp;BSTArray,&nbsp;</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">BalancedBST<img src="http://www.cppblog.com/Images/dot.gif">.\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;BalancedBST&nbsp;bBSTArray[</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;printBSTArray(cout,&nbsp;bBSTArray,&nbsp;</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;system(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">pause</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<p><br>其结果如下：<br><br>&nbsp; <img height=435 alt="" src="http://www.cppblog.com/images/cppblog_com/springsnow/6.jpg" width=663 border=0><br><br>&nbsp;可以看到程序并不如我们所期望的那样，这说明什么呢？<br>&nbsp;arr[i],表示的是*（arr+i）,但是arr+i所指向的地址偏离arr所指向的地址是i*(an object in the array)。<br>因为参数被声明为BST数组类型，那么数组的每个元素必须是BST，那么它们的间隔也毕定是i*sizeof(BST)。如果传入BalancedBST数组，编译器可能就会犯错误，在这种情况下，编译器就会假定数组里每个对象的大小都和BST的大小一样。而通常派生类要比基类有更多的成员变量，所以派生类一般都比基类对象大。所以我们就看到了如上的结果。<br><br>&nbsp;试图通过一个基类指针删除一个包含派生类对象的数组，也会有同样的问题。<br><br>所以不要把多台应用到数组上，还是很有好处的。</p>
<img src ="http://www.cppblog.com/SpringSnow/aggbug/96922.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/SpringSnow/" target="_blank">Sandy</a> 2009-09-22 11:57 <a href="http://www.cppblog.com/SpringSnow/archive/2009/09/22/96922.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++学习——More Effective C++ 基础议题</title><link>http://www.cppblog.com/SpringSnow/archive/2009/09/15/96194.html</link><dc:creator>Sandy</dc:creator><author>Sandy</author><pubDate>Tue, 15 Sep 2009 02:27:00 GMT</pubDate><guid>http://www.cppblog.com/SpringSnow/archive/2009/09/15/96194.html</guid><wfw:comment>http://www.cppblog.com/SpringSnow/comments/96194.html</wfw:comment><comments>http://www.cppblog.com/SpringSnow/archive/2009/09/15/96194.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/SpringSnow/comments/commentRss/96194.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/SpringSnow/services/trackbacks/96194.html</trackback:ping><description><![CDATA[<p>最近忙着看书，但发觉记忆不是很好。看时明明白白的东西，一会就忘了。觉得还是记录下来，好记性不如烂笔头，减慢阅读的速度，增加思考的时间。<br><br>More Effective C++之一 基础议题<br><br><strong>条款1：区分指针和引用</strong><br>这个可以理解为：指针和引用有什么区别。<br>一是指针可以为空，而引用不能为空。<br>引用必须要指代某个对象。由于引用总是要指代一个对象，C++要求引用必须初始化。不存在空引用，则意味着引用比使用指针更高效。因为使用引用之前不需要测试它是否有效，而指针通常需要检查其是否为空。<br>二是指针可以被重新赋值用以指向另外一个不同的对象，而引用总是指向初始化时它所指代的对象。<br><br><strong>条款2：优先考虑C++风格的类型转换<br></strong>这个可以有两个问题需要明白：一是C风格的类型转换有什么缺点；二是C++风格的类型转换的优点。<br>首先我们来看C风格类型转换的缺点：<br>其一是可以通过它们在任意类型之间进行转换。有些转换差别很大，但C风格的类型没有做区分，行为有些粗鲁。<br>其二是C风格的类型转换很难进行查找。<br><br>c++风格的类型转换：有4种类型转换，分别是static_cast, const_cast, dynamic_cast和reinterpret_cast。<br>使用时应写成<br>static_cast&lt;typde&gt; (expression)，其他同理。<br><br>static_cast 针对一种不涉及继承的类型实施转换，也不涉及const转换的时候，就可以使用static_cast转换。<br>const_cast用来去除掉一个表达式的const属性或volatile属性。强调的是通过这个转换你要做的唯一一件事情就是改变某些东西的const属性或者volatile属性。目前为止，最通常的用法是去除掉一个对象的const属性。<br>dynamic_cast，用来针对一个继承体系做向下或者横向的安全转换。用dynamic_cast 把指向基类的指针（或引用）转换成指向派生类或者基类的兄弟类的指针（或引用），而且同时可以知道转换是否成功。空指针或者异常意味着失败。<br>reinterpret_cast最常见的用法是用来在函数指针之间进行类型转换。这种转换常常是由（编译器的）实现所定义的，致使reinterpret_cast几乎不可移植。对函数指针实施类型转换是不可移植的，而且在某些情况下会产生不正确的。<br><br>C++风格的类型转换的优点：有确切的含义并容易识别，他们允许编译器诊断类型转换所产生的错误，不会使这些错误就在不知不觉的情况下被漏掉。<br><br>该上班了，其他待续。。。<br><br><br><br></p>
<img src ="http://www.cppblog.com/SpringSnow/aggbug/96194.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/SpringSnow/" target="_blank">Sandy</a> 2009-09-15 10:27 <a href="http://www.cppblog.com/SpringSnow/archive/2009/09/15/96194.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>判断计算机的大小尾数的方法</title><link>http://www.cppblog.com/SpringSnow/archive/2009/07/28/91477.html</link><dc:creator>Sandy</dc:creator><author>Sandy</author><pubDate>Tue, 28 Jul 2009 07:04:00 GMT</pubDate><guid>http://www.cppblog.com/SpringSnow/archive/2009/07/28/91477.html</guid><wfw:comment>http://www.cppblog.com/SpringSnow/comments/91477.html</wfw:comment><comments>http://www.cppblog.com/SpringSnow/archive/2009/07/28/91477.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/SpringSnow/comments/commentRss/91477.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/SpringSnow/services/trackbacks/91477.html</trackback:ping><description><![CDATA[这是《程序员面试攻略》上的一道题，先前也有一位公司同事问过我，今天有重新拿起看了一下。<br><br>书中介绍了两种方法<br>第一种是这样的利用强制类型转换<br>bool endianness()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int testNum;<br>&nbsp;&nbsp;&nbsp;&nbsp; char*&nbsp; ptr;<br><br>&nbsp;&nbsp;&nbsp;&nbsp; testNum = 1;<br>&nbsp;&nbsp;&nbsp;&nbsp; ptr = (char*)&amp;testNum;<br>&nbsp;&nbsp;&nbsp;&nbsp; return ptr;<br>}<br><br>这个方法还比较好理解。<br><br>第二种方法就是利用union。<br>bool endianness()<br>{<br>&nbsp;&nbsp;&nbsp; union{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int theInteger;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char singleChar;<br>&nbsp;&nbsp; }endianTesg;<br><br>&nbsp;&nbsp; endianTest.theInteger = 1;<br>&nbsp;&nbsp; return endianTest.singleChar;<br>}<br><br>这种方法很巧妙。带着困意就是没有看懂，一个个问号就蹦出来了？这是为什么呢？<br><br>说实话，union在学习和工作中用的还真的不是很多。其用法还真是不记得。<br>所以赶快到网上去搜了一下。有篇文章还不错，我看懂了。<br><a href="http://blog.ednchina.com/likee/20666/message.aspx#"><u><font color=#800080>共用体union用法讲解</font></u></a><br>链接地址：<a href="http://blog.ednchina.com/likee/20666/message.aspx">http://blog.ednchina.com/likee/20666/message.aspx</a><br><br>Union表示几个变量公用一个内存位置, 在不同的时间保存不同的数据类型和不同长度的变量。其长度为Union中最大的变量长度。 <br><br>这样，我们就不难理解上面的程序，theInteger和singleChar是共用一个内存位置的，如果是小尾数法的话，那么singleChar为1，对应theInteger的低八位；如果是大尾数法的话，那么singleChar为0， 对应theInteger的低八位。<br><br><br>继续努力学习！<br>朝着梦想加油前进。<br>
<img src ="http://www.cppblog.com/SpringSnow/aggbug/91477.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/SpringSnow/" target="_blank">Sandy</a> 2009-07-28 15:04 <a href="http://www.cppblog.com/SpringSnow/archive/2009/07/28/91477.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>类设计者的核查表</title><link>http://www.cppblog.com/SpringSnow/archive/2009/07/25/91098.html</link><dc:creator>Sandy</dc:creator><author>Sandy</author><pubDate>Sat, 25 Jul 2009 00:32:00 GMT</pubDate><guid>http://www.cppblog.com/SpringSnow/archive/2009/07/25/91098.html</guid><wfw:comment>http://www.cppblog.com/SpringSnow/comments/91098.html</wfw:comment><comments>http://www.cppblog.com/SpringSnow/archive/2009/07/25/91098.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/SpringSnow/comments/commentRss/91098.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/SpringSnow/services/trackbacks/91098.html</trackback:ping><description><![CDATA[<meta http-equiv="Content-Type" content="text/html; charset="utf-8"">
<meta name="ProgId" content="Word.Document">
<meta name="Generator" content="Microsoft Word 9">
<meta name="Originator" content="Microsoft Word 9">
<link rel="File-List" href="file:///C:/DOCUME%7E1/hongzhao/LOCALS%7E1/Temp/msoclip1/01/clip_filelist.xml"><!--[if gte mso 9]><xml>
<w:worddocument>
<w:view>Normal</w:view>
<w:zoom>0</w:zoom>
<w:punctuationkerning/>
<w:drawinggridverticalspacing>7.8 磅</w:drawinggridverticalspacing>
<w:displayhorizontaldrawinggridevery>0</w:displayhorizontaldrawinggridevery>
<w:displayverticaldrawinggridevery>2</w:displayverticaldrawinggridevery>
<w:compatibility>
<w:spaceforul/>
<w:balancesinglebytedoublebytewidth/>
<w:donotleavebackslashalone/>
<w:ultrailspace/>
<w:donotexpandshiftreturn/>
<w:adjustlineheightintable/>
<w:usefelayout/>
</w:compatibility>
<w:donotoptimizeforbrowser/>
</w:worddocument>
</xml><![endif]--><style>
<!--
/* Font Definitions */
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-alt:SimSun;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:"\@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
mso-pagination:none;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:宋体;
mso-font-kerning:1.0pt;}
/* Page Definitions */
@page
{mso-page-border-surround-header:no;
mso-page-border-surround-footer:no;}
@page Section1
{size:612.0pt 792.0pt;
margin:72.0pt 90.0pt 72.0pt 90.0pt;
mso-header-margin:36.0pt;
mso-footer-margin:36.0pt;
mso-paper-source:0;}
div.Section1
{page:Section1;}
/* List Definitions */
@list l0
{mso-list-id:1204827719;
mso-list-type:hybrid;
mso-list-template-ids:1404875998 1761645648 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;}
@list l0:level1
{mso-level-number-format:japanese-counting;
mso-level-text:%1、;
mso-level-tab-stop:21.0pt;
mso-level-number-position:left;
margin-left:21.0pt;
text-indent:-21.0pt;}
ol
{margin-bottom:0cm;}
ul
{margin-bottom:0cm;}
-->
</style>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-family: 宋体;">去同学那玩，看到这么一本书《</span><span lang="EN-US">C++</span><span style="font-family: 宋体;">沉思录》。这本书很早听过，但是没有读过。于是捧起书读了几章，感觉很是不错。其中第四章就是讲&#8220;类设计者的核查表&#8221;。虽然用</span><span lang="EN-US">c++</span><span style="font-family: 宋体;">有几年，但是有一些东西还是需要铭记于心的。</span></p>
<p class="MsoNormal"><span lang="EN-US"><!--[if !supportEmptyParas]-->&nbsp;<!--[endif]--><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 14pt; font-family: 宋体;">类设计者的核查表</span><span style="font-size: 14pt;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-top: 0cm; margin-bottom: 0.0001pt; text-indent: -21pt; line-height: 150%;"><!--[if !supportLists]--><strong><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">一、<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></strong><!--[endif]--><strong><span style="font-size: 12pt; font-family: 宋体;">您的类需要一个构造函数么？</span></strong><strong><span style="font-size: 12pt;" lang="EN-US"><o:p></o:p></span></strong></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-family: 宋体;">有些类太简单，无需构造函数，但有些类太复杂，他们需要构造函数来隐藏它们的内部工作方式。</span></p>
<p class="MsoNormal" style="margin-top: 0cm; margin-bottom: 0.0001pt; text-indent: -21pt; line-height: 150%;"><!--[if !supportLists]--><span style="font-family: 宋体;" lang="EN-US">二、<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><!--[endif]--><strong><span style="font-size: 12pt; font-family: 宋体;">您的数据成员是私有的么？</span></strong></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-family: 宋体;">通常使用公有的数据成员不是什么好事，因为类设计者无法控制何时访问这些成员。</span></p>
<p class="MsoNormal" style="margin-top: 0cm; margin-bottom: 0.0001pt; text-indent: -21pt; line-height: 150%;"><!--[if !supportLists]--><span style="font-family: 宋体;" lang="EN-US">三、<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><!--[endif]--><strong><span style="font-size: 12pt; font-family: 宋体;">您的类需要一个无参的构造函数么？</span></strong></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-family: 宋体;">如果一个类已经有了构造函数，想声明该类的对象可以不必显示地初始化它们，则必须显示地写一个无参的构造函数。</span></p>
<p class="MsoNormal" style="margin-top: 0cm; margin-bottom: 0.0001pt; text-indent: -21pt; line-height: 150%;"><!--[if !supportLists]--><span style="font-family: 宋体;" lang="EN-US">四、<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><!--[endif]--><strong><span style="font-size: 12pt; font-family: 宋体;">是不是每一个构造函数初始化所有的数据成员？</span></strong></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-family: 宋体;">构造函数的用途就是用一种明确定义的状态来设置对象。对象的状态由对象的数据成员进行反映。每个构造函数都要负责为所有的数据成员设置经过明确定义的值。</span></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-family: 宋体;">有时这种说法也未必总是正确的。有时，类会有一些数据成员，它们只在它们的对象存在了一定时间之后才有意义。提这个问题，只是激励你进行思考。</span></p>
<p class="MsoNormal" style="margin-top: 0cm; margin-bottom: 0.0001pt; text-indent: -21pt; line-height: 150%;"><!--[if !supportLists]--><span style="font-family: 宋体;" lang="EN-US">五、<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><!--[endif]--><strong><span style="font-size: 12pt; font-family: 宋体;">类需要构造函数么？</span></strong></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-family: 宋体;">不是所有有构造函数的类都需要构造函数。如果深入考虑一个类要做些什么，那么该类是否需要析构函数的问题就十分明显了。应该问一问该类是否分配了资源，而这些资源又不会有成员函数自动释放，这就足够了。特别是那些构造函数里包含了</span><span lang="EN-US">new</span><span style="font-family: 宋体;">表达式的类，通常要在析构函数中加上相应的</span><span lang="EN-US">delete</span><span style="font-family: 宋体;">表达式，所以需要一个虚析构函数。</span></p>
<p class="MsoNormal" style="margin-top: 0cm; margin-bottom: 0.0001pt; text-indent: -21pt; line-height: 150%;"><!--[if !supportLists]--><strong><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">六、<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></strong><!--[endif]--><strong><span style="font-size: 12pt; font-family: 宋体;">类需要一个虚析构函数么？</span></strong><strong><span style="font-size: 12pt;" lang="EN-US"><o:p></o:p></span></strong></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-family: 宋体;">有些类需要虚析构函数只是为了声明他们的析构函数是虚的。当然，决不会用做基类的类是不需要虚析构函数的：任何虚函数只在继承的情况下才有用。</span></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-family: 宋体;">虚析构函数通常是空的。</span></p>
<p class="MsoNormal" style="margin-top: 0cm; margin-bottom: 0.0001pt; text-indent: -21pt; line-height: 150%;"><!--[if !supportLists]--><span style="font-family: 宋体;" lang="EN-US">七、<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><!--[endif]--><strong><span style="font-size: 12pt; font-family: 宋体;">你的类需要复制构造函数么？</span></strong></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-family: 宋体;">很多时候答案都是&#8220;不&#8221;，但是有时候答案是&#8220;是&#8221;。关键在于复制该类对象是否就相当于复制其数据成员和基类对象。如果并不相当，就需要复制构造函数。</span></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-family: 宋体;">如果你的类在构造函数内分配资源，则可能需要一个显示的复制构造函数来管理资源。有析构函数的类通常是析构函数来释放构造函数分配的资源，这通常说明需要一个复制构造函数。（空的虚析构函数除外）</span></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-family: 宋体;">如果不想用户能够复制该类的对象，就声明复制构造函数为私有的。如果其他的成员不会使用这些成员函数，声明就足够了，没有必要定义它们。</span></p>
<p class="MsoNormal" style="margin-top: 0cm; margin-bottom: 0.0001pt; text-indent: -21pt; line-height: 150%;"><!--[if !supportLists]--><span style="font-family: 宋体;" lang="EN-US">八、<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><!--[endif]--><strong><span style="font-size: 12pt; font-family: 宋体;">你的类需要一个赋值操作么？</span></strong></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-family: 宋体;">如果需要复制构造函数，同理多半也会需要一个赋值操作。</span></p>
<p class="MsoNormal" style="margin-top: 0cm; margin-bottom: 0.0001pt; text-indent: -21pt; line-height: 150%;"><!--[if !supportLists]--><span style="font-family: 宋体;" lang="EN-US">九、<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><!--[endif]--><strong><span style="font-size: 12pt; font-family: 宋体;">你的赋值操作符能正确地将对象赋给对象本身么？</span></strong></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-family: 宋体;">赋值总是用新值取代目标对象的旧值。如果原对象和目标对象是同一个，而我们又奉行&#8220;先释放旧值，再复制&#8221;的行事规程，那么就可能在还没有实施复制之前就把原对象销毁了。</span></p>
<p class="MsoNormal" style="margin-top: 0cm; margin-bottom: 0.0001pt; text-indent: -21pt; line-height: 150%;"><!--[if !supportLists]--><span style="font-family: 宋体;" lang="EN-US">十、<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><!--[endif]--><strong><span style="font-size: 12pt; font-family: 宋体;">你的类需要定义关系操作符么？</span></strong></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-family: 宋体;">如果你的类逻辑上支持相等操作，那么提供</span><span lang="EN-US">operate== </span><span style="font-family: 宋体;">和</span><span lang="EN-US">operate!=</span><span style="font-family: 宋体;">可能会有好处。类似的，如果你的类的值有某种排序关系，那就可能会想提供余下的关系操作符。只要它们想创建你的类型的有序集合，你就必须提供关系操作符。</span></p>
<p class="MsoNormal" style="margin-top: 0cm; margin-bottom: 0.0001pt; text-indent: -21pt; line-height: 150%;"><!--[if !supportLists]--><span style="font-family: 宋体;" lang="EN-US">十一<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"></span></span><strong><span style="font-size: 12pt; font-family: 宋体;">&nbsp; 删除数组时你记住了用</span></strong><strong><span style="font-size: 12pt;" lang="EN-US">delete[]</span></strong><strong><span style="font-size: 12pt; font-family: 宋体;">么？</span></strong></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-family: 宋体;">这个形式的存在，是</span><span lang="EN-US">C++</span><span style="font-family: 宋体;">希望在保持与</span><span lang="EN-US">C</span><span style="font-family: 宋体;">的兼容性的同时关注效率。</span><span lang="EN-US">C++</span><span style="font-family: 宋体;">要求用户告知要被删除的是不是数组。如果是，该实现就可能会提供另一个地方来存储长度，因为与数组所需的内存量相比，这个常数的开销会小很多。</span></p>
<p class="MsoNormal" style="margin-top: 0cm; margin-bottom: 0.0001pt; text-indent: -21pt; line-height: 150%;"><!--[if !supportLists]--><span style="font-family: 宋体;" lang="EN-US">十二 &nbsp;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">
</span></span><!--[endif]--><strong><span style="font-size: 12pt; font-family: 宋体;">记得在复制构造函数和赋值操作符的参数类型中加上了</span></strong><strong><span style="font-size: 12pt;" lang="EN-US">const</span></strong><strong><span style="font-size: 12pt; font-family: 宋体;">么？</span></strong></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-family: 宋体;">复制构造函数应该是像</span><span lang="EN-US">X::X(const X&amp;)</span><span style="font-family: 宋体;">这样，毕竟复制对象不会改变原对象。实际上，由于绑定一个非</span><span lang="EN-US">const</span><span style="font-family: 宋体;">引用到一个临时对象是非法的，使用</span><span lang="EN-US">X::X(X&amp;)</span><span style="font-family: 宋体;">作为复制构造函数不会允许复制任何特殊表达式的结果。同样道理适用于赋值。</span></p>
<p class="MsoNormal" style="margin-top: 0cm; margin-bottom: 0.0001pt; text-indent: -21pt; line-height: 150%;"><!--[if !supportLists]--><span style="font-family: 宋体;" lang="EN-US">十三&nbsp;&nbsp; <span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;"></span></span><strong><span style="font-size: 12pt; font-family: 宋体;">如果函数有引用参数，它们应该是</span></strong><strong><span style="font-size: 12pt;" lang="EN-US">const</span></strong><strong><span style="font-size: 12pt; font-family: 宋体;">引用么？</span></strong></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-family: 宋体;">只有当函数想改变参数时，它才应该有不用</span><span lang="EN-US">const</span><span style="font-family: 宋体;">声明的引用参数。</span></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span lang="EN-US"><!--[if !supportEmptyParas]-->&nbsp;<!--[endif]--><o:p></o:p></span></p>
&nbsp;&nbsp; <span style="font-size: 10.5pt; font-family: 宋体;">其中很多作者提到，提这些问题并不是希望去寻求答案，只是希望能够激励你进行思考。所以当我们设计一个类的时候，多思考一下，有没有什么地方需要注意的，我们设计的类将会更合理，更健壮一些。</span><img src ="http://www.cppblog.com/SpringSnow/aggbug/91098.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/SpringSnow/" target="_blank">Sandy</a> 2009-07-25 08:32 <a href="http://www.cppblog.com/SpringSnow/archive/2009/07/25/91098.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>int 与char的转换</title><link>http://www.cppblog.com/SpringSnow/archive/2009/07/24/91058.html</link><dc:creator>Sandy</dc:creator><author>Sandy</author><pubDate>Fri, 24 Jul 2009 09:45:00 GMT</pubDate><guid>http://www.cppblog.com/SpringSnow/archive/2009/07/24/91058.html</guid><wfw:comment>http://www.cppblog.com/SpringSnow/comments/91058.html</wfw:comment><comments>http://www.cppblog.com/SpringSnow/archive/2009/07/24/91058.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/SpringSnow/comments/commentRss/91058.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/SpringSnow/services/trackbacks/91058.html</trackback:ping><description><![CDATA[<p>今天抱着书在做这么一道题：<br>整数/字符串转换<br>编写两个转换例程。第一个例程将一个字符串转换成带符号的整数。您可以假定这个字符串只包含数字和符号字符（'-'）,是一个格式正确的整数，而且这个数字在int类型的范围之内。第二个例程将Int类型中存储的有符号整数转换回字符串。<br><br>其中碰到了int与char的转换问题。这个还真的把我难住了。我先用最笨的方法switch进行了转换。你也知道这肯定不是最优的方法。直接转换，值也肯定不对。<br><br>后来发现竟然是这么使用的，赶快记录下来。<br>1、int 转换成char<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 例如：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp; n = 1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char ch = char(n + '0');<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不过需要注意，此处的n只能是0-9之间的字符<br>2、char转换成Int<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char ch = '9';<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int n = int(ch) - int('0');<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;此处ch也是&#8216;0&#8217;至&#8216;9&#8217;的数字字符<br><br>多多学习，抓住机遇。</p>
<img src ="http://www.cppblog.com/SpringSnow/aggbug/91058.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/SpringSnow/" target="_blank">Sandy</a> 2009-07-24 17:45 <a href="http://www.cppblog.com/SpringSnow/archive/2009/07/24/91058.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转载: .NET中，接口与类的区别 </title><link>http://www.cppblog.com/SpringSnow/archive/2009/06/26/88588.html</link><dc:creator>Sandy</dc:creator><author>Sandy</author><pubDate>Fri, 26 Jun 2009 09:32:00 GMT</pubDate><guid>http://www.cppblog.com/SpringSnow/archive/2009/06/26/88588.html</guid><wfw:comment>http://www.cppblog.com/SpringSnow/comments/88588.html</wfw:comment><comments>http://www.cppblog.com/SpringSnow/archive/2009/06/26/88588.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/SpringSnow/comments/commentRss/88588.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/SpringSnow/services/trackbacks/88588.html</trackback:ping><description><![CDATA[1、接口类似于类，但接口的成员都没有执行方式，它只是方法、属性、事件和索引符的组合而已，并且也只能包含这四种成员；类除了这四种成员之外还可以别的成员(如字段)。<br>2、不能实例化一个接口，接口只包括成员的签名；而类可以实例化(abstract类除外)。<br>3、接口没有构造函数，类有构造函数。<br>4、接口不能进行运算符的重载，类可以进行运算符重载。<br>5、接口的成员没有任何修饰符，其成员总是公共的，而类的成员则可以有修饰符(如：虚拟或者静态)。<br>6、派生于接口的类必须实现接口中所有成员的执行方式，而从类派生则不然。<br><br>那么为什么还要有接口呢？<br>&nbsp;&nbsp;&nbsp;&nbsp;主要原因是它是一种有效的契约。类有一些成员，不考虑把这些成员组合在一起，类只是一个拥有各种方法、字段和属性的列表，但为了能以某种方式使用类，必须知道类能执行那些功能，具体的操作就是声明执行一个或多个接口的类，类执行接口的方式是从接口中派生，再提供这个接口中定义的所有成员的执行方式。<br><br>摘自: <a href="http://www.cnblogs.com/ajayumi/archive/2008/06/10/1216746.html">http://www.cnblogs.com/ajayumi/archive/2008/06/10/1216746.html</a>
<img src ="http://www.cppblog.com/SpringSnow/aggbug/88588.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/SpringSnow/" target="_blank">Sandy</a> 2009-06-26 17:32 <a href="http://www.cppblog.com/SpringSnow/archive/2009/06/26/88588.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>成员初始化列表 </title><link>http://www.cppblog.com/SpringSnow/archive/2009/06/18/87959.html</link><dc:creator>Sandy</dc:creator><author>Sandy</author><pubDate>Thu, 18 Jun 2009 05:33:00 GMT</pubDate><guid>http://www.cppblog.com/SpringSnow/archive/2009/06/18/87959.html</guid><wfw:comment>http://www.cppblog.com/SpringSnow/comments/87959.html</wfw:comment><comments>http://www.cppblog.com/SpringSnow/archive/2009/06/18/87959.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/SpringSnow/comments/commentRss/87959.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/SpringSnow/services/trackbacks/87959.html</trackback:ping><description><![CDATA[对于成员初始化列表，熟悉有不是很熟悉。什么情况下使用呢？心里还是发怵，说不出所以然来。<br><br>学习是王道，搜索是方法。有了网络就是好。<br><br>摘自：<a href="http://www.cnblogs.com/heyutao/archive/2009/05/22/1487081.html">http://www.cnblogs.com/heyutao/archive/2009/05/22/1487081.html</a><br><br><a class=postTitle2 id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/heyutao/archive/2009/05/22/1487081.html"><u><span>成员初始化列表</span></u></a> <br><br>类对象的构造顺序是这样的：<br>1.分配内存，调用构造函数时，隐式/显示的初始化各数据成员<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 初始化阶段可以是显式的或隐式的，取决于是否存在成员初始化表。隐式初始化阶段按照声明的顺序依次调用所有基类的缺省构造函数，然后是所有成员类对象的缺省构造函数。<br>2.进入构造函数后在构造函数中执行一般计算<br>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 计算阶段由构造函数体内的所有语句构成。在计算阶段中，数据成员的设置被认为是赋值，而不是初始化。</p>
<p>使用初始化列表有两个原因：<br></p>
<p><strong>1.必须这样做：</strong> <br></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 三种情况下需要使用初始化成员列表<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1）对象成员；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2）const修饰的成员；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3）引用成员数据；<br><br>(1)如果有一个类成员，它本身是一个类或者是一个结构，而且这个成员它只有一个带参数的构造函数，而没有默认构造函数，这时要对这个类成员进行初始化，就必须调用这个类成员的带参数的构造函数，如果没有初始化列表，那么他将无法完成第一步，就会报错。<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;ABC<br><img id=Codehighlighter1_31_126_Open_Image onclick="this.style.display='none'; Codehighlighter1_31_126_Open_Text.style.display='none'; Codehighlighter1_31_126_Closed_Image.style.display='inline'; Codehighlighter1_31_126_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_31_126_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_31_126_Closed_Text.style.display='none'; Codehighlighter1_31_126_Open_Image.style.display='inline'; Codehighlighter1_31_126_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_31_126_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_31_126_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img id=Codehighlighter1_82_83_Open_Image onclick="this.style.display='none'; Codehighlighter1_82_83_Open_Text.style.display='none'; Codehighlighter1_82_83_Closed_Image.style.display='inline'; Codehighlighter1_82_83_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_82_83_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_82_83_Closed_Text.style.display='none'; Codehighlighter1_82_83_Open_Image.style.display='inline'; Codehighlighter1_82_83_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;ABC(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;x,</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;y,</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;z):a(x),b(y),c(z)</span><span id=Codehighlighter1_82_83_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_82_83_Open_Text><span style="COLOR: #000000">{}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;a;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;b;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;c;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;MyClass<br><img id=Codehighlighter1_143_219_Open_Image onclick="this.style.display='none'; Codehighlighter1_143_219_Open_Text.style.display='none'; Codehighlighter1_143_219_Closed_Image.style.display='inline'; Codehighlighter1_143_219_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_143_219_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_143_219_Closed_Text.style.display='none'; Codehighlighter1_143_219_Open_Image.style.display='inline'; Codehighlighter1_143_219_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_143_219_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_143_219_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img id=Codehighlighter1_194_195_Open_Image onclick="this.style.display='none'; Codehighlighter1_194_195_Open_Text.style.display='none'; Codehighlighter1_194_195_Closed_Image.style.display='inline'; Codehighlighter1_194_195_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_194_195_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_194_195_Closed_Text.style.display='none'; Codehighlighter1_194_195_Open_Image.style.display='inline'; Codehighlighter1_194_195_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;MyClass(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;a,</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;b,</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;c):abc(a,b,c)</span><span id=Codehighlighter1_194_195_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_194_195_Open_Text><span style="COLOR: #000000">{}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;ABC&nbsp;abc;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br><img id=Codehighlighter1_234_272_Open_Image onclick="this.style.display='none'; Codehighlighter1_234_272_Open_Text.style.display='none'; Codehighlighter1_234_272_Closed_Image.style.display='inline'; Codehighlighter1_234_272_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_234_272_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_234_272_Closed_Text.style.display='none'; Codehighlighter1_234_272_Open_Image.style.display='inline'; Codehighlighter1_234_272_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_234_272_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_234_272_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;MyClass&nbsp;o(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<p>(2)当类成员中含有一个const成员时<br></p>
<p>(3)当类成员中含有一个引用时 <br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_56_167_Open_Image onclick="this.style.display='none'; Codehighlighter1_56_167_Open_Text.style.display='none'; Codehighlighter1_56_167_Closed_Image.style.display='inline'; Codehighlighter1_56_167_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_56_167_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_56_167_Closed_Text.style.display='none'; Codehighlighter1_56_167_Open_Image.style.display='inline'; Codehighlighter1_56_167_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;ConstRef&nbsp;</span><span id=Codehighlighter1_56_167_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_56_167_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;ConstRef(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;print();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;a;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;b;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">const成员</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">c;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">引用</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top></span><span style="COLOR: #000000">}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>ConstRef::ConstRef(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i):b(i),c(a)</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">含有一个const对象时，或者是一个引用时使用初始化成员列表</span><span style="COLOR: #008000"><br><img id=Codehighlighter1_239_316_Open_Image onclick="this.style.display='none'; Codehighlighter1_239_316_Open_Text.style.display='none'; Codehighlighter1_239_316_Closed_Image.style.display='inline'; Codehighlighter1_239_316_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_239_316_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_239_316_Closed_Text.style.display='none'; Codehighlighter1_239_316_Open_Image.style.display='inline'; Codehighlighter1_239_316_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_239_316_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_239_316_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;a&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;i;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;ok<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">b&nbsp;=&nbsp;i;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;错误<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">c&nbsp;=&nbsp;a;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;错误</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top></span><span style="COLOR: #000000">}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;ConstRef::print()<br><img id=Codehighlighter1_341_400_Open_Image onclick="this.style.display='none'; Codehighlighter1_341_400_Open_Text.style.display='none'; Codehighlighter1_341_400_Closed_Image.style.display='inline'; Codehighlighter1_341_400_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_341_400_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_341_400_Closed_Text.style.display='none'; Codehighlighter1_341_400_Open_Image.style.display='inline'; Codehighlighter1_341_400_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_341_400_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_341_400_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">a</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">b</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">c</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br><img id=Codehighlighter1_413_463_Open_Image onclick="this.style.display='none'; Codehighlighter1_413_463_Open_Text.style.display='none'; Codehighlighter1_413_463_Closed_Image.style.display='inline'; Codehighlighter1_413_463_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_413_463_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_413_463_Closed_Text.style.display='none'; Codehighlighter1_413_463_Open_Image.style.display='inline'; Codehighlighter1_413_463_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_413_463_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_413_463_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;ConstRef&nbsp;o(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;o.print();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<p><br>&nbsp;</p>
<p>2.效率要求这样做：</p>
<p>类对象的构造顺序显示，进入构造函数体后，进行的是计算，是对他们的赋值操作，显然，赋值和初始化是不同的，这样就体现出了效率差异，如果不用成员初始化列表，那么类对自己的类成员分别进行的是一次隐式的默认构造函数的调用，和一次复制操作符的调用，如果是类对象，这样做效率就得不到保障。<br><br>注意：构造函数需要初始化的数据成员，不论是否显式的出现在构造函数的成员初始化列表中，都会在该处完成初始化，并且初始化的顺序和其在声明时的顺序是一致的，与列表的先后顺序无关，所以要特别注意，保证两者顺序一致才能真正保证其效率。<br><br>现在明白为什么要使用成员初始化列表了。<br><br>这里再强调一下类的初始化的顺序，应该是类成员变量的初始化不是按照初始化表的顺序被初始化的，而是按照在类中声明的顺序被初始化的。<br>这是摘自：<a id=viewpost1_TitleUrl href="http://www.cppblog.com/xczhang/archive/2008/01/22/41613.html"><font color=#000000>Effective C++学习笔记：初始化列表中成员列出的顺序和它们在类中声明的顺序相同</font></a> <a href="http://www.cppblog.com/xczhang/archive/2008/01/22/41613.html">http://www.cppblog.com/xczhang/archive/2008/01/22/41613.html</a></p>
<p>为什么会这样呢？我们知道，对一个对象的所有成员来说，它们的析构函数被调用的顺序总是和它们在构造函数里被创建的顺序相反。那么，如果允许上面的情况（即，成员按它们在初始化列表上出现的顺序被初始化）发生，编译器就要为每一个对象跟踪其成员初始化的顺序，以保证它们的析构函数以正确的顺序被调用。这会带来昂贵的开销。所以，为了避免这一开销，同一种类型的所有对象在创建（构造）和摧毁（析构）过程中对成员的处理顺序都是相同的,而不管成员在初始化列表中的顺序如何。</p>
<p>注意：上述内容不适用于static变量，static变量应该在类的构造函数前被初始化。</p>
<p><br><br>好文章拿来学习，请作者见谅哈！</p>
<img src ="http://www.cppblog.com/SpringSnow/aggbug/87959.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/SpringSnow/" target="_blank">Sandy</a> 2009-06-18 13:33 <a href="http://www.cppblog.com/SpringSnow/archive/2009/06/18/87959.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>为什么拷贝构造函数必须为引用传递，不能是值传递？ </title><link>http://www.cppblog.com/SpringSnow/archive/2009/06/18/87945.html</link><dc:creator>Sandy</dc:creator><author>Sandy</author><pubDate>Thu, 18 Jun 2009 03:13:00 GMT</pubDate><guid>http://www.cppblog.com/SpringSnow/archive/2009/06/18/87945.html</guid><wfw:comment>http://www.cppblog.com/SpringSnow/comments/87945.html</wfw:comment><comments>http://www.cppblog.com/SpringSnow/archive/2009/06/18/87945.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/SpringSnow/comments/commentRss/87945.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/SpringSnow/services/trackbacks/87945.html</trackback:ping><description><![CDATA[对于拷贝构造函数引用传递，似乎司空见惯，认为理所当然。但是被问起这个问题，的确是一片茫然，为什么呢？<br><br>去网上搜索了一下，的确有很多这方面的知识讲解。<br><br>我们先看一下CSDN上的一个帖子的回答：<br>简单的回答是为了防止递归引用。<br>具体一些可以这么讲：<br>&nbsp;当一个对象需要以值方式传递时，编译器会生成代码调用它的拷贝构造函数以生成一个复本。如果类A的拷贝构造函数是以值方式传递一个类A对象作为参数的话，当需要调用类A的拷贝构造函数时，需要以值方式传进一个A的对象作为实参；&nbsp;而以值方式传递需要调用类A的拷贝构造函数；结果就是调用类A的拷贝构造函数导致又一次调用类A的拷贝构造函数，这就是一个无限递归。<br><br>这个解释还是蛮具体的。<br>利用值传递的话，会导致递归引用。<br><br>还有一片文章也谈到了这个问题， 我觉得写得也非常好！<br><br><a class=postTitle2 id=AjaxHolder_ctl01_TitleUrl href="http://www.cnblogs.com/chio/archive/2007/09/14/893299.html"><font color=#6466b3>为什么拷贝构造函数必须为引用传递，不能是值传递？</font></a> <br>链接地址：<a href="http://www.cnblogs.com/chio/archive/2007/09/14/893299.html">http://www.cnblogs.com/chio/archive/2007/09/14/893299.html</a><br><br>其中讲到了3个问题<br><strong>1是拷贝构造函数的作用。<br></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 作用就是用来复制对象的，在使用这个对象的实例来初始化这个对象的一个新的实例。<br><strong>2是参数传递过程到底发生了什么？<br></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 将地址传递和值传递统一起来，归根结底还是传递的是"值"(地址也是值，只不过通过它可以找到另一个值)！<br>i)值传递:<br>&nbsp;&nbsp;&nbsp;&nbsp;对于内置数据类型的传递时，直接赋值拷贝给形参(注意形参是函数内局部变量)；<br>&nbsp;&nbsp;&nbsp; 对于类类型的传递时，需要首先调用该类的拷贝构造函数来初始化形参(局部对象)；如void foo(class_type obj_local){}, 如果调用foo(obj);&nbsp; 首先class_type obj_local(obj)&nbsp;,这样就定义了局部变量obj_local供函数内部使用<br>ii)引用传递:<br>&nbsp;&nbsp;&nbsp;&nbsp;无论对内置类型还是类类型，传递引用或指针最终都是传递的地址值！而地址总是指针类型(属于简单类型), 显然参数传递时，按简单类型的赋值拷贝，而不会有拷贝构造函数的调用(对于类类型).<br><strong>3是在类中有指针数据成员时，拷贝构造函数的使用？<br></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果不显式声明拷贝构造函数的时候，编译器也会生成一个默认的拷贝构造函数，而且在一般的情况下运行的也很好。但是在遇到类有指针数据成员时就出现问题了：因为默认的拷贝构造函数是按成员拷贝构造，这导致了两个不同的指针(如ptr1=ptr2)指向了相同的内存。当一个实例销毁时，调用析构函数free(ptr1)释放了这段内存，那么剩下的一个实例的指针ptr2就无效了，在被销毁的时候free(ptr2)就会出现错误了, 这相当于重复释放一块内存两次。这种情况必须显式声明并实现自己的拷贝构造函数，来为新的实例的指针分配新的内存。<br><br>问题1和2回答了为什么拷贝构造函数使用值传递会产生无限递归调用的问题；<br>问题3回答了回答了在类中有指针数据成员时，拷贝构造函数使用值传递等于白显式定义了拷贝构造函数，因为默认的拷贝构造函数就是这么干的。<br><br>这样我终于看明白了。作者写得的确好。<br><br><br><br>
<img src ="http://www.cppblog.com/SpringSnow/aggbug/87945.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/SpringSnow/" target="_blank">Sandy</a> 2009-06-18 11:13 <a href="http://www.cppblog.com/SpringSnow/archive/2009/06/18/87945.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转: 浅谈C++的智能指针</title><link>http://www.cppblog.com/SpringSnow/archive/2009/06/18/87941.html</link><dc:creator>Sandy</dc:creator><author>Sandy</author><pubDate>Thu, 18 Jun 2009 02:47:00 GMT</pubDate><guid>http://www.cppblog.com/SpringSnow/archive/2009/06/18/87941.html</guid><wfw:comment>http://www.cppblog.com/SpringSnow/comments/87941.html</wfw:comment><comments>http://www.cppblog.com/SpringSnow/archive/2009/06/18/87941.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/SpringSnow/comments/commentRss/87941.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/SpringSnow/services/trackbacks/87941.html</trackback:ping><description><![CDATA[摘自: <a href="http://www.cppblog.com/yearner/archive/2008/11/09/66447.html">http://www.cppblog.com/yearner/archive/2008/11/09/66447.html</a><br><br>对于智能指针，也只是听说而已，对深层的东西也不甚了解。昨日又重听这一字眼，想想多少也该了解一些。<br><br>浅谈C++的智能指针<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 内存泄露是C++程序员都头疼的大<span id=rlt_4 style="CURSOR: pointer; BORDER-BOTTOM: #fa891b 1px solid" onclick="sendmsg('pw_ajax.php','action=relatetag&amp;tagname=问题',this.id)">问题</span>。C++缺乏像JAVA、C#一样，拥有GC这么一项有利的武器，它将内存管理的部分<span id=rlt_2 style="CURSOR: pointer; BORDER-BOTTOM: #fa891b 1px solid" onclick="sendmsg('pw_ajax.php','action=relatetag&amp;tagname=权限',this.id)">权限</span>交给了程序员。虽然GC的存在节约了开发、排错的时间与成本，但是C++为了追求运行<span id=rlt_1 style="CURSOR: pointer; BORDER-BOTTOM: #fa891b 1px solid" onclick="sendmsg('pw_ajax.php','action=relatetag&amp;tagname=速度',this.id)">速度</span>而20年来坚决不予补充进其标准。（题外话：C++通过加大开发难度去换取执行速度的做法，在现在看来不知是否能给与正面的评价，还是留给将来再说吧。）<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 从此，在堆上申请了内存忘了释放、所造成的内存泄露的问题就一直困扰着C++程序员。也许为了稍许弥补没有垃圾回收器所造成的开发门槛高，各大厂商开发的C++库中都像COM学习引入智能指针试图解决部分目前存在的问题。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 智能指针是存储指向动态分配（堆）对象指针的类, 用于生存期控制, 能够确保自动正确的销毁动态分配的对象，防止内存泄露。它的一种通用实现技术是使用引用计数(reference count)。智能指针类将一个计数器与类指向的对象相关联，引用计数跟踪该类有多少个对象共享同一指针。每次创建类的新对象时，初始化指针并将引用计数置为1；当对象作为另一对象的副本而创建时，拷贝构造函数拷贝指针并增加与之相应的引用计数；对一个对象进行赋值时，赋值操作符减少左操作数所指对象的引用计数（如果引用计数为减至0，则删除对象），并增加右操作数所指对象的引用计数；调用析构函数时，构造函数减少引用计数（如果引用计数减至0，则删除基础对象）。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 说到智能指针，我们一定要看看标准C++库提供的&#8220;搞笑的&#8221;智能指针:auto_ptr。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 标准库中提供了C++程序的基本设施。虽然C++标准库随着C++标准折腾了许多年，直到标准的出台才正式定型，网上评论C++标准库时都说：&#8220;在标准库的实现上却很令人欣慰得看到多种实现，并且已被实践证明为有工业级别强度的佳作。&#8221;但目前的标准C++中，只有一种独苗智能指针：std::auto_ptr。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr指针是一个RAII对象,它初始化时获得资源,析构时自动释放资源(生命期结束).它的缺点数不胜数：<br>1、auto_ptr要求一个对象只能有一个拥有者，严禁一物二主<br>2、缺少对引用数和数组的支持。<br>3、不可将auto_ptr对象作为STL容器的元素。C++标准明确禁止这样做，否则可能会碰到不可预见的结果。（这一条晕死一<span id=rlt_5 style="CURSOR: pointer; BORDER-BOTTOM: #fa891b 1px solid" onclick="sendmsg('pw_ajax.php','action=relatetag&amp;tagname=大片',this.id)">大片</span>）。<br>4、auto_ptr在被复制的时候会传输所有权<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 反正由此可见：标准库的智能指针就是无甚大用。<br><br>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; 在这样的情况下，C++标准委员会自然需要考虑引入新的智能指针。目前由C++标准委员会库工作组发起的Boost 组织开发了Boost系列智能指针。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在Boost中的智能指针有五种： scoped_ptr，scoped_array，shared_ptr，shared_array，weak_ptr.<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 前4种完全是针对标准库中的auto_ptr提出解决方案，如：scope_ptr是针对&#8220;auto_ptr在被复制的时候会传输所有权&#8221;这一弱点提出的。最后一种没见过，看名字像是弱引用智能指针，我怀疑<span id=rlt_3 style="CURSOR: pointer; BORDER-BOTTOM: #fa891b 1px solid" onclick="sendmsg('pw_ajax.php','action=relatetag&amp;tagname=是不是',this.id)">是不是</span>类似于JAVA中弱引用一样,有待进一步学习。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 还查到一篇：<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span id=ArticleTitle1_ArticleTitle1_lblTitle><strong>C++深度探索系列：智能指针(Smart Pointer) [一]</strong></span>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://dev.csdn.net/develop/article/17/17530.shtm">http://dev.csdn.net/develop/article/17/17530.shtm</a><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有空可以看看！<br><br><br>
<img src ="http://www.cppblog.com/SpringSnow/aggbug/87941.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/SpringSnow/" target="_blank">Sandy</a> 2009-06-18 10:47 <a href="http://www.cppblog.com/SpringSnow/archive/2009/06/18/87941.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何输出“hello, world”</title><link>http://www.cppblog.com/SpringSnow/archive/2009/05/05/81930.html</link><dc:creator>Sandy</dc:creator><author>Sandy</author><pubDate>Tue, 05 May 2009 05:01:00 GMT</pubDate><guid>http://www.cppblog.com/SpringSnow/archive/2009/05/05/81930.html</guid><wfw:comment>http://www.cppblog.com/SpringSnow/comments/81930.html</wfw:comment><comments>http://www.cppblog.com/SpringSnow/archive/2009/05/05/81930.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/SpringSnow/comments/commentRss/81930.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/SpringSnow/services/trackbacks/81930.html</trackback:ping><description><![CDATA[看到我这样写，可能你会笑话我，写了这么长时间了，&#8220;hello, world&#8221;输出谁不会写呢？<br><br>的确， 我们简单的这样写，如下，就可以输出一个&#8220;hello, world&#8221;.<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br><img id=Codehighlighter1_54_103_Open_Image onclick="this.style.display='none'; Codehighlighter1_54_103_Open_Text.style.display='none'; Codehighlighter1_54_103_Closed_Image.style.display='inline'; Codehighlighter1_54_103_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_54_103_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_54_103_Closed_Text.style.display='none'; Codehighlighter1_54_103_Open_Image.style.display='inline'; Codehighlighter1_54_103_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_54_103_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_54_103_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Hello,&nbsp;World!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>但现在的条件是你需要在main函数里什么也不做，就输出&#8220;hello, world&#8221;。<br><br>可能你很快就想到了。但是我很笨，没有想到。不过我现在会了。<br><br>我们可以这样做，<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;A<br><img id=Codehighlighter1_51_112_Open_Image onclick="this.style.display='none'; Codehighlighter1_51_112_Open_Text.style.display='none'; Codehighlighter1_51_112_Closed_Image.style.display='inline'; Codehighlighter1_51_112_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_51_112_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_51_112_Closed_Text.style.display='none'; Codehighlighter1_51_112_Open_Image.style.display='inline'; Codehighlighter1_51_112_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_51_112_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_51_112_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;A()<br><img id=Codehighlighter1_69_110_Open_Image onclick="this.style.display='none'; Codehighlighter1_69_110_Open_Text.style.display='none'; Codehighlighter1_69_110_Closed_Image.style.display='inline'; Codehighlighter1_69_110_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_69_110_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_69_110_Closed_Text.style.display='none'; Codehighlighter1_69_110_Open_Image.style.display='inline'; Codehighlighter1_69_110_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</span><span id=Codehighlighter1_69_110_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_69_110_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Hello,&nbsp;World!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>A&nbsp;a;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br><img id=Codehighlighter1_133_147_Open_Image onclick="this.style.display='none'; Codehighlighter1_133_147_Open_Text.style.display='none'; Codehighlighter1_133_147_Closed_Image.style.display='inline'; Codehighlighter1_133_147_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_133_147_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_133_147_Closed_Text.style.display='none'; Codehighlighter1_133_147_Open_Image.style.display='inline'; Codehighlighter1_133_147_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_133_147_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_133_147_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>声明一个全局的对象a, 这样的话，它会调用它的构造函数，也就会打印出&#8220;Hello,world&#8221;.<br>还有一种方法也是定义一个全局对象，只是利用方法，如下：<br><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;Func()<br><img id=Codehighlighter1_54_103_Open_Image onclick="this.style.display='none'; Codehighlighter1_54_103_Open_Text.style.display='none'; Codehighlighter1_54_103_Closed_Image.style.display='inline'; Codehighlighter1_54_103_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_54_103_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_54_103_Closed_Text.style.display='none'; Codehighlighter1_54_103_Open_Image.style.display='inline'; Codehighlighter1_54_103_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_54_103_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_54_103_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Hello,&nbsp;World!</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;Func();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br><img id=Codehighlighter1_134_148_Open_Image onclick="this.style.display='none'; Codehighlighter1_134_148_Open_Text.style.display='none'; Codehighlighter1_134_148_Closed_Image.style.display='inline'; Codehighlighter1_134_148_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_134_148_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_134_148_Closed_Text.style.display='none'; Codehighlighter1_134_148_Open_Image.style.display='inline'; Codehighlighter1_134_148_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_134_148_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_134_148_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br><br>其实这主要是一个全局对象的初始化顺序的问题。<br><strong>全局对象在调用 main之前初始化， 在退出main之后析构。<br><br></strong>理解了这个，输出&#8220;Hello,World&#8221;便很简单了。
<img src ="http://www.cppblog.com/SpringSnow/aggbug/81930.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/SpringSnow/" target="_blank">Sandy</a> 2009-05-05 13:01 <a href="http://www.cppblog.com/SpringSnow/archive/2009/05/05/81930.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>计算机计算浮点数时的舍入误差</title><link>http://www.cppblog.com/SpringSnow/archive/2009/04/15/79994.html</link><dc:creator>Sandy</dc:creator><author>Sandy</author><pubDate>Wed, 15 Apr 2009 05:38:00 GMT</pubDate><guid>http://www.cppblog.com/SpringSnow/archive/2009/04/15/79994.html</guid><wfw:comment>http://www.cppblog.com/SpringSnow/comments/79994.html</wfw:comment><comments>http://www.cppblog.com/SpringSnow/archive/2009/04/15/79994.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/SpringSnow/comments/commentRss/79994.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/SpringSnow/services/trackbacks/79994.html</trackback:ping><description><![CDATA[在<a href="http://radovi.javaeye.com/blog/322096">http://radovi.javaeye.com/blog/322096</a>这篇博客里谈到计算机计算浮点数时的舍入误差，我也在VS2005下进行了相应的实验，如下代码：<br><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br><img id=Codehighlighter1_54_136_Open_Image onclick="this.style.display='none'; Codehighlighter1_54_136_Open_Text.style.display='none'; Codehighlighter1_54_136_Closed_Image.style.display='inline'; Codehighlighter1_54_136_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_54_136_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_54_136_Closed_Text.style.display='none'; Codehighlighter1_54_136_Open_Image.style.display='inline'; Codehighlighter1_54_136_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_54_136_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_54_136_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">&nbsp;f&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">4.35</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">(f</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;system(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">pause</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>&nbsp;的确打印出来的结果是434.<br><br>老男孩给出的解释是这样的：<br>这个问题和二进制的表示有很大关系 <br>简单地说 <br>计算机不能准确表示诸如1/10等一类分数 <br><br>我查到了一篇文章：<a href="http://support.microsoft.com/kb/214118/zh-cn">http://support.microsoft.com/kb/214118/zh-cn</a>，如下,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IEEE 754 标准是一种方法很容易操作的压缩方式存储浮点数。 Intel coprocessors 和实现浮点数学的大多数基于 PC 的程序使用此标准。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IEEE 754 指定编号，以减少存储要求，并允许该内置二进制算法指令来处理数据以相对较快速的方式的所有微处理器上可用的二进制格式存储。 但是，是简单的、 非重复的十进制数字的某些数字转换为重复不能存储的完美的准确性的二进制数字。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 例如数 1 / 10 可以表示简单小数的十进制数字系统中： <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .1 <br>&nbsp;&nbsp;&nbsp;&nbsp; 但是，二进制格式中的数目将十进制重复的二进制文件： <br>&nbsp;&nbsp;&nbsp;&nbsp; 0001100011000111000111 （和这样上）<br>&nbsp;&nbsp;&nbsp;&nbsp; 此数字无法表示按有限数量的空间。 因此，此数字向下舍入的大约-2.78E-17 存储。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果获取给定的结果执行多个的算术运算，这些舍入误差可能具有累积性。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 看来是和二进制的表示有很大关系。
<img src ="http://www.cppblog.com/SpringSnow/aggbug/79994.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/SpringSnow/" target="_blank">Sandy</a> 2009-04-15 13:38 <a href="http://www.cppblog.com/SpringSnow/archive/2009/04/15/79994.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>读《小P成长记》</title><link>http://www.cppblog.com/SpringSnow/archive/2009/03/12/76330.html</link><dc:creator>Sandy</dc:creator><author>Sandy</author><pubDate>Thu, 12 Mar 2009 05:59:00 GMT</pubDate><guid>http://www.cppblog.com/SpringSnow/archive/2009/03/12/76330.html</guid><wfw:comment>http://www.cppblog.com/SpringSnow/comments/76330.html</wfw:comment><comments>http://www.cppblog.com/SpringSnow/archive/2009/03/12/76330.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/SpringSnow/comments/commentRss/76330.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/SpringSnow/services/trackbacks/76330.html</trackback:ping><description><![CDATA[昨天才开始认真读《小P成长记》，发现真的很好看。<br><br>学习这么久，才发现思考方法的转变还是很重要的。我们往往缺少一位向老C一样的好老师，能够慢慢引导我们学习。<br><br>机会难得，我们与小P一样快快成长吧。<br><br>读到第一桶第九碗了，<br>对里面的一些思想和方法很赞同，转过来：<br><br><span style="FONT-FAMILY: Courier New"><span style="FONT-FAMILY: Verdana"><strong>思想：</strong></span></span><br><span style="FONT-FAMILY: Courier New"><span style="FONT-FAMILY: Verdana"><strong>1. 以数据为中心思考问题的解决之道。</strong></span></span><br><span style="FONT-FAMILY: Courier New"><span style="FONT-FAMILY: Verdana"><strong>2. 将对同类数据的操作放在相同的编译单元中。</strong></span></span><br><span style="FONT-FAMILY: Courier New"><span style="FONT-FAMILY: Verdana"><strong>3. 信息隐藏，而不是暴露，以将问题的规模控制在可理解的范围。</strong></span></span><br><br><br><span style="FONT-FAMILY: Courier New"><span style="FONT-FAMILY: Verdana"><strong>方法：</strong></span></span><br><span style="FONT-FAMILY: Courier New"><span style="FONT-FAMILY: Verdana"><strong>1. 首先关注整体，而不是细节。</strong></span></span><br><span style="FONT-FAMILY: Courier New"><span style="FONT-FAMILY: Verdana"><strong>2. 先考虑测试，更先于编码。</strong></span></span><br><span style="FONT-FAMILY: Courier New"><span style="FONT-FAMILY: Verdana"><strong>3. 先用伪代码编程，以体现程序的意图，再用具体代码完善之。</strong></span></span><br><span style="FONT-FAMILY: Courier New"><span style="FONT-FAMILY: Verdana"><strong>4. 迅速构建可编译通过的，并且可执行的框架程序，使用测试代码测试之。</strong></span></span><br><span style="FONT-FAMILY: Courier New"><span style="FONT-FAMILY: Verdana"><strong>5. 将以上方法反复应用于子模块，直到问题被解决。</strong></span></span><br><span style="FONT-FAMILY: Courier New"><span style="FONT-FAMILY: Verdana"><strong>6. 在上下文环境中提取对其他模块的需求。</strong></span></span><br><span style="FONT-FAMILY: Courier New"><span style="FONT-FAMILY: Verdana"><strong>7. 先写.h文件，后写.c文件。</strong></span></span><br><span style="FONT-FAMILY: Courier New"><span style="FONT-FAMILY: Verdana"><strong>8. 先快速实现一个可行的解法，再根据反馈信息优化之。<br></strong></span></span><br>如果大家也关心小P，就一同到那看看，链接地址：<a href="http://www.cppblog.com/enderson/archive/2009/02/18/74215.html">http://www.cppblog.com/enderson/archive/2009/02/18/74215.html</a><br>
<img src ="http://www.cppblog.com/SpringSnow/aggbug/76330.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/SpringSnow/" target="_blank">Sandy</a> 2009-03-12 13:59 <a href="http://www.cppblog.com/SpringSnow/archive/2009/03/12/76330.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>vector的一点疏忽</title><link>http://www.cppblog.com/SpringSnow/archive/2008/12/29/70647.html</link><dc:creator>Sandy</dc:creator><author>Sandy</author><pubDate>Mon, 29 Dec 2008 03:37:00 GMT</pubDate><guid>http://www.cppblog.com/SpringSnow/archive/2008/12/29/70647.html</guid><wfw:comment>http://www.cppblog.com/SpringSnow/comments/70647.html</wfw:comment><comments>http://www.cppblog.com/SpringSnow/archive/2008/12/29/70647.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/SpringSnow/comments/commentRss/70647.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/SpringSnow/services/trackbacks/70647.html</trackback:ping><description><![CDATA[<p>今天遇到一个奇怪的问题,是有关于vector的.<br>他一直提示: subcript&nbsp; out of range.这是指下标越界的问题,怎么也没有理解如何下标越界了.<br>代码我这样写的:<br>for (size_t&nbsp;&nbsp; i= vc.size()-1; i &gt;= 0; i--)<br>{<br>&nbsp;&nbsp;&nbsp; &nbsp;....<br>}<br>觉得这个问题很蹊跷,在什么地方越界的呢?<br><br>跟踪了一下i值的变化,原来i值的变化并非按照我想像的那样进行,当i为零后,再减一,并不是变为一个负数,而是变成了一个非常大的正数,所以此时提醒越界了.<br><br>原来是这个原因.<br><br>对于vector的用法不是很熟,我暂时改为<br>int size = vc.size()-1;<br>for (int i = size; i&gt;=0; i--)<br>{<br>&nbsp;......<br>}<br><br>这样就解决了越界的问题.<br><br>那么发生这个问题的原因是什么呢?<br><br>我们需要清楚size_t的类型是什么?<br>size_t&nbsp;&nbsp;&nbsp;<br>&nbsp;有时就是unsigned &nbsp; int;&nbsp;&nbsp;&nbsp;<br>有时就是unsigned &nbsp; long; <br><br>通过这个我们就知道size_t是无符号整数,所以这个问题也就清楚了.<br><br>那有没有很好的方法来解决这个问题呢?<br>不像我那么笨的输出呢?<br><br>有:<br>for (std::vector&lt;int&gt;::reverse_iterator i = vc.rbegin(); i &lt; vc.rend(); i++)<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp; ......<br>&nbsp;}<br><br>这样就把vctor中的元素颠倒了一个顺序输出了.<br><br>欢迎大家指教.</p>
<img src ="http://www.cppblog.com/SpringSnow/aggbug/70647.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/SpringSnow/" target="_blank">Sandy</a> 2008-12-29 11:37 <a href="http://www.cppblog.com/SpringSnow/archive/2008/12/29/70647.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转:临界区(Critical section)与互斥体(Mutex)的区别</title><link>http://www.cppblog.com/SpringSnow/archive/2008/12/26/70464.html</link><dc:creator>Sandy</dc:creator><author>Sandy</author><pubDate>Fri, 26 Dec 2008 10:39:00 GMT</pubDate><guid>http://www.cppblog.com/SpringSnow/archive/2008/12/26/70464.html</guid><wfw:comment>http://www.cppblog.com/SpringSnow/comments/70464.html</wfw:comment><comments>http://www.cppblog.com/SpringSnow/archive/2008/12/26/70464.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/SpringSnow/comments/commentRss/70464.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/SpringSnow/services/trackbacks/70464.html</trackback:ping><description><![CDATA[1、临界区只能用于对象在同一进程里线程间的互斥访问；互斥体可以用于对象进程间或线程间的互斥访问。<br>2、临界区是非内核对象，只在用户态进行锁操作，速度快；互斥体是内核对象，在核心态进行锁操作，速度慢。<br>3、临界区和互斥体在Windows平台都下可用；Linux下只有互斥体可用。<br>文章出处：<a href="http://www.diybl.com/course/3_program/c++/cppsl/2008525/117880.html">http://www.diybl.com/course/3_program/c++/cppsl/2008525/117880.html</a>
<img src ="http://www.cppblog.com/SpringSnow/aggbug/70464.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/SpringSnow/" target="_blank">Sandy</a> 2008-12-26 18:39 <a href="http://www.cppblog.com/SpringSnow/archive/2008/12/26/70464.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：Win32 临界区实现原理浅析</title><link>http://www.cppblog.com/SpringSnow/archive/2008/12/01/68288.html</link><dc:creator>Sandy</dc:creator><author>Sandy</author><pubDate>Mon, 01 Dec 2008 06:05:00 GMT</pubDate><guid>http://www.cppblog.com/SpringSnow/archive/2008/12/01/68288.html</guid><wfw:comment>http://www.cppblog.com/SpringSnow/comments/68288.html</wfw:comment><comments>http://www.cppblog.com/SpringSnow/archive/2008/12/01/68288.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/SpringSnow/comments/commentRss/68288.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/SpringSnow/services/trackbacks/68288.html</trackback:ping><description><![CDATA[<p>摘自：<a href="http://www.diybl.com/course/3_program/c++/cppjs/2008426/111619.html">http://www.diybl.com/course/3_program/c++/cppjs/2008426/111619.html</a><br>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;去年11月的MSDN杂志曾刊登过一篇文章 <a href="http://msdn.microsoft.com/zh-cn/magazine/cc164040(en-us).aspx">Break Free of Code Deadlocks in Critical Sections Under Windows </a>，Matt Pietrek 和 Russ Osterlund 两位对临界区(Critical Section)的内部实现做了一次简短的介绍，但点到为止，没有继续深入下去，当时给我的感觉就是痒痒的，呵呵，于是用IDA和SoftIce大致分析了一下临界区的实现，大致弄明白了原理后也就没有深究。现在乘着Win2k源码的东风，重新分析一下这块的内容，做个小小的总结吧 :P<br>&nbsp;&nbsp;&nbsp;&nbsp; 临界区(Critical Section)是Win32中提供的一种轻量级的同步机制，与互斥(Mutex)和事件(Event)等内核同步对象相比，临界区是完全在用户态维护的，所以仅能在同一进程内供线程同步使用，但也因此无需在使用时进行用户态和核心态之间的切换，工作效率大大高于其它同步机制。<br>&nbsp;&nbsp;&nbsp;&nbsp; 临界区的使用方法非常简单，使用 InitializeCriticalSection 或 InitializeCriticalSectionAndSpinCount 函数初始化一个 CRITICAL_SECTION 结构；使用 SetCriticalSectionSpinCount 函数设置临界区的Spin计数器；然后使用 EnterCriticalSection 或 TryEnterCriticalSection 获取临界区的所有权；完成需要同步的操作后，使用 LeaveCriticalSection 函数释放临界区；最后使用 DeleteCriticalSection 函数析构临界区结构。<br>&nbsp;&nbsp;&nbsp;&nbsp; 以下是MSDN中提供的一个简单的例子： </p>
<p>&nbsp;&nbsp;&nbsp; 以下为引用： </p>
<p>&nbsp;// Global variable<br>&nbsp;CRITICAL_SECTION CriticalSection; </p>
<p>&nbsp;void main()<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp; ...</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; // Initialize the critical section one time only.<br>&nbsp;&nbsp;&nbsp;&nbsp; if (!InitializeCriticalSectionAndSpinCount(&amp;CriticalSection, 0x80000400) )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br>&nbsp;&nbsp;&nbsp;&nbsp; ...</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; // Release resources used by the critical section object.<br>&nbsp;&nbsp;&nbsp;&nbsp; DeleteCriticalSection(&amp;CriticalSection)<br>&nbsp;}</p>
<p>&nbsp;DWORD WINAPI ThreadProc( LPVOID lpParameter )<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp; ...</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; // Request ownership of the critical section.<br>&nbsp;&nbsp;&nbsp;&nbsp; EnterCriticalSection(&amp;CriticalSection);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; // Access the shared resource.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; // Release ownership of the critical section.<br>&nbsp;&nbsp;&nbsp;&nbsp; LeaveCriticalSection(&amp;CriticalSection);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; ...<br>&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 首先看看构造和析构临界区结构的函数。<br>&nbsp;&nbsp;&nbsp;&nbsp; InitializeCriticalSection 函数(ntosdll esource.c:1210)实际上是调用 InitializeCriticalSectionAndSpinCount 函数(resource.c:1266)完成功能的，只不过传入一个值为0的初始Spin计数器；InitializeCriticalSectionAndSpinCount 函数主要完成两部分工作：初始化 RTL_CRITICAL_SECTION 结构和 RTL_CRITICAL_SECTION_DEBUG 结构。前者是临界区的核心结构，下面将着重讨论；后者是调试用结构，Matt 那篇文章里面分析的很清楚了，我这儿就不罗嗦了 :P<br>&nbsp;&nbsp;&nbsp;&nbsp; RTL_CRITICAL_SECTION结构在winnt.h中定义如下：</p>
<p>以下为引用： </p>
<p>&nbsp;typedef struct _RTL_CRITICAL_SECTION {<br>&nbsp;&nbsp;&nbsp;&nbsp; PRTL_CRITICAL_SECTION_DEBUG DebugInfo; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; //<br>&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp; The following three fields control entering and exiting the critical<br>&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp; section for the resource<br>&nbsp;&nbsp;&nbsp;&nbsp; //</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; LONG LockCount;<br>&nbsp;&nbsp;&nbsp;&nbsp; LONG RecursionCount;<br>&nbsp;&nbsp;&nbsp;&nbsp; HANDLE OwningThread;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // from the thread''s<br><br>ClientId-&gt;UniqueThread<br>&nbsp;&nbsp;&nbsp;&nbsp; HANDLE LockSemaphore;<br>&nbsp;&nbsp;&nbsp;&nbsp; ULONG_PTR SpinCount;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // force size on 64-bit systems when packed<br>&nbsp;} RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; InitializeCriticalSectionAndSpinCount 函数中首先对临界区结构进行了初始化</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; DebugInfo 字段指向初始化临界区时分配的RTL_CRITICAL_SECTION_DEBUG结构；<br>&nbsp;&nbsp;&nbsp;&nbsp; LockCount 字段是临界区中最重要的字段，初始值为-1，当临界区被获取(Hold)时此字段大于等于0；<br>&nbsp;&nbsp;&nbsp;&nbsp; RecursionCount 字段保存当前临界区所有者线程的获取缓冲区嵌套层数，初始值为0；<br>&nbsp;&nbsp;&nbsp;&nbsp; OwningThread 字段保存当前临界区所有者线程的句柄，初始值为0；<br>&nbsp;&nbsp;&nbsp;&nbsp; LockSemaphore 字段实际上是一个auto-reset的事件句柄，用于唤醒等待获取临界区的阻塞线程，初始值为0；<br>&nbsp;&nbsp;&nbsp;&nbsp; SpinCount 字段用于在多处理器环境下完成轻量级的CPU见同步，单处理器时没有使用（初始值为0），多处理器时设置为SpinCount参数值（最大为MAX_SPIN_COUNT=0x00ffffff）。此外 RtlSetCriticalSectionSpinCount 函数(resource.c:1374)的代码与这儿设置SpinCount的代码完全一样。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 初始化临界区结构后，函数会根据SpinCount参数的一个标志位判断是否需要预先初始化 LockSemaphore 字段，如果需要则使用NtCreateEvent创建一个具有访问权限的同步用事件核心对象，初始状态为没有激发。这一初始化本来是在 EnterCriticalSection 函数中完成的，将之显式提前可以进一步优化 EnterCriticalSection 函数的性能。<br>&nbsp;&nbsp;&nbsp;&nbsp; 值得注意的是，这一特性仅对Win2k有效。MSDN里面说明如下：</p>
<p>以下为引用： </p>
<p>&nbsp;Windows 2000:&nbsp; If the high-order bit is set, the function preallocates the event used by the EnterCriticalSection function. Do not set this bit if you are creating a large number of critical section objects, because it will consume a significant amount of nonpaged pool. This flag is not necessary on Windows XP and later, and it is ignored.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 与之对应的 DeleteCriticalSection 函数完成关闭事件句柄和是否调试结构的功能。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 临界区真正的核心代码在win2kprivate tosdlli386critsect.asm里面，包括_RtlEnterCriticalSection、_RtlTryEnterCriticalSection和_RtlLeaveCriticalSection三个函数。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; _RtlEnterCriticalSection 函数 (critsect.asm:85) 首先检查SpinCount是否为0，如果不为0则处理多处理器架构下的问题[分支1]；如为0则使用原子操作给LockCount加一，并判断是否其值为0。如果加一后LockCount大于0，则此临界区已经被获取[分支2]；如为0则获取当前线程TEB中的线程句柄，保存在临界区的OwningThread字段中，并将RecursionCount设置为1。调试版本则调用RtlpCriticalSectionIsOwned函数在调试模式下验证此缓冲区是被当前线程获取的，否则在调试模式下激活调试器。最后还会更新TEB的CountOfOwnedCriticalSections计数器，以及临界区调试结构中的EntryCount字段。<br>&nbsp;&nbsp;&nbsp;&nbsp; 如果此临界区已经被获取[分支2]，则判断获取临界区的线程句柄是否与当前线程相符。如果是同一线程则直接将RecursionCount和调试结构的EntryCount字段加一；如果不是当前线程，则调用RtlpWaitForCriticalSection函数等待此临界区，并从头开始执行获取临界区的程序。<br>&nbsp;&nbsp;&nbsp;&nbsp; 多CPU情况的分支处理方式类似，只是多了对SpinCount的双重检查处理。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 接着的_RtlTryEnterCriticalSection(critsect.asm:343)函数是一个轻量级的尝试获取临界区的函数。伪代码如下：</p>
<p>以下为引用： </p>
<p>&nbsp;if(CriticalSection-&gt;LockCount == -1)<br>&nbsp;{<br>&nbsp;&nbsp; // 临界区可用<br>&nbsp;&nbsp; CriticalSection-&gt;LockCount = 0;<br>&nbsp;&nbsp; CriticalSection-&gt;OwningThread = TEB-&gt;ClientID;<br>&nbsp;&nbsp; CriticalSection-&gt;RecursionCount = 1; </p>
<p>&nbsp;&nbsp; return TRUE;<br>&nbsp;}<br>&nbsp;else<br>&nbsp;{<br>&nbsp;&nbsp; if(CriticalSection-&gt;OwningThread == TEB-&gt;ClientID)<br>&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp; // 临界区是当前线程获取<br>&nbsp;&nbsp;&nbsp;&nbsp; CriticalSection-&gt;LockCount++;<br>&nbsp;&nbsp;&nbsp;&nbsp; CriticalSection-&gt;RecursionCount++;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; return TRUE;<br>&nbsp;&nbsp; }<br>&nbsp;&nbsp; else<br>&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp; // 临界区已被其它线程获取<br>&nbsp;&nbsp;&nbsp;&nbsp; return FALSE;<br>&nbsp;&nbsp; }<br>&nbsp;}<br>&nbsp;<br>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 最后的_RtlLeaveCriticalSection(critsect.asm:271)函数释放已获取的临界区，实现就比较简单了，实际上就是对嵌套计数器和锁定计数器进行操作。伪代码如下：</p>
<p>&nbsp;</p>
<p>以下为引用： </p>
<p>&nbsp;if(--CriticalSection-&gt;RecursionCount == 0)<br>&nbsp;{<br>bsp;&nbsp; // 临界区已不再被使用<br>&nbsp;&nbsp; CriticalSection-&gt;OwningThread = 0; <br>&nbsp;</p>
<p>&nbsp;&nbsp; if(--CriticalSection-&gt;LockCount)<br>&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp; // 仍有线程锁定在临界区上<br>&nbsp;&nbsp;&nbsp;&nbsp; _RtlpUnWaitCriticalSection(CriticalSection)<br>&nbsp;&nbsp; }<br>&nbsp;}<br>&nbsp;else<br>&nbsp;{<br>&nbsp;&nbsp; --CriticalSection-&gt;LockCount<br>&nbsp;}</p>
<img src ="http://www.cppblog.com/SpringSnow/aggbug/68288.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/SpringSnow/" target="_blank">Sandy</a> 2008-12-01 14:05 <a href="http://www.cppblog.com/SpringSnow/archive/2008/12/01/68288.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>宏的学习一</title><link>http://www.cppblog.com/SpringSnow/archive/2008/12/01/68287.html</link><dc:creator>Sandy</dc:creator><author>Sandy</author><pubDate>Mon, 01 Dec 2008 05:54:00 GMT</pubDate><guid>http://www.cppblog.com/SpringSnow/archive/2008/12/01/68287.html</guid><wfw:comment>http://www.cppblog.com/SpringSnow/comments/68287.html</wfw:comment><comments>http://www.cppblog.com/SpringSnow/archive/2008/12/01/68287.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/SpringSnow/comments/commentRss/68287.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/SpringSnow/services/trackbacks/68287.html</trackback:ping><description><![CDATA[<span>一、宏中&#8220;</span><span>#</span><span>&#8221;和&#8220;</span><span>##</span><span>&#8221;的用法：</span>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一般用法：</span><span>使用&#8220;</span><span>#</span><span>&#8221;把宏参数变为一个字符串，用</span><span>&#8221;##&#8221;</span><span>把两个宏参数结合在一起<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 例子：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;TEST1(x)&nbsp;(cout&lt;&lt;id##x&lt;&lt;endl);</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;TEST2(p)&nbsp;(cout&lt;&lt;#p&lt;&lt;endl);</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;main()<br><img id=Codehighlighter1_126_312_Open_Image onclick="this.style.display='none'; Codehighlighter1_126_312_Open_Text.style.display='none'; Codehighlighter1_126_312_Closed_Image.style.display='inline'; Codehighlighter1_126_312_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_126_312_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_126_312_Closed_Text.style.display='none'; Codehighlighter1_126_312_Open_Image.style.display='inline'; Codehighlighter1_126_312_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_126_312_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_126_312_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;id1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1001</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;id2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1002</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;TEST1(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">);&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;==&nbsp;cout&lt;&lt;&nbsp;id1&nbsp;&lt;&lt;&nbsp;endl;</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;TEST2(</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">);&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;==&nbsp;cout&lt;&lt;&nbsp;"2"&nbsp;&lt;&lt;&nbsp;endl;</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;TEST1(</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">);&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;==&nbsp;cout&lt;&lt;&nbsp;id2&nbsp;&lt;&lt;&nbsp;endl;</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;system(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">pause</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><br>二、防止一个头文件被重复包含<br></span><span lang=EN-US>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #ifndef COMDEF_H<br></span><span lang=EN-US>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #define COMDEF_H</span> <br><span lang=EN-US>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">头文件内容<br></span><span lang=EN-US>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #endif<br></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;当你所建的工程有多个源文件组成时，很可能会在多个文件里头包含了同一个头文件，如果借用上面的宏定义就能够避免同一个头文件被重复包含时进行多次编译。因为当它编译第一个头文件时总是没有定义</span><span lang=EN-US>#define COMDEF_H</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，那么它将编译一遍头文件中所有的内容，包括定义</span><span lang=EN-US>#define COMDEF_H</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。这样编译再往下进行时如果遇到同样要编译的头文件，那么由于语句</span><span lang=EN-US>#ifndef COMDEF_H</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的存在它将不再重复的编译这个头文件。<br><br>三、常用的宏定义<br>&nbsp; __DATE__<br>&nbsp; 进行预处理的日期（&#8220;Mmm dd yyyy&#8221;形式的字符串文字）<br><br>&nbsp; __FILE__<br>&nbsp; 代表当前源代码文件名的字符串文字<br><br>&nbsp; __LINE__<br>&nbsp; 代表当前源代码中的行号的整数常量<br><br>&nbsp; __TIME__<br>&nbsp; 源文件编译时间，格式微&#8220;hh：mm：ss&#8221;<br><br>参考文章：<br>&nbsp;&nbsp;&nbsp;<a href="http://blog.readnovel.com/article/htm/tid_900939.html"><span id=articletitle><font color=#000066>C中的预编译宏定义</font></span></a>&nbsp; <a href="http://blog.readnovel.com/article/htm/tid_900939.html">http://blog.readnovel.com/article/htm/tid_900939.html</a><br>&nbsp;&nbsp; C标准中一些预定义的宏 <a href="http://www.programfan.com/article/2883.html">http://www.programfan.com/article/2883.html</a><br>&nbsp;&nbsp; C语言常用宏定义技巧&nbsp; <a href="http://blog.21ic.com/user1/3074/archives/2008/51567.html">http://blog.21ic.com/user1/3074/archives/2008/51567.html</a><br>&nbsp;&nbsp; C语言宏定义技巧（常用宏定义） <a href="http://blog.21ic.com/user1/69/archives/2006/13695.html">http://blog.21ic.com/user1/69/archives/2006/13695.html</a><br>&nbsp;&nbsp; 宏定义：<a href="http://blog.csdn.net/believefym/archive/2007/10/21/1836162.aspx">http://blog.csdn.net/believefym/archive/2007/10/21/1836162.aspx</a><br><br>好好学习！<br>&nbsp;</span>
<img src ="http://www.cppblog.com/SpringSnow/aggbug/68287.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/SpringSnow/" target="_blank">Sandy</a> 2008-12-01 13:54 <a href="http://www.cppblog.com/SpringSnow/archive/2008/12/01/68287.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>分享：C++中extern “C”含义深层探索</title><link>http://www.cppblog.com/SpringSnow/archive/2008/12/01/68276.html</link><dc:creator>Sandy</dc:creator><author>Sandy</author><pubDate>Mon, 01 Dec 2008 03:43:00 GMT</pubDate><guid>http://www.cppblog.com/SpringSnow/archive/2008/12/01/68276.html</guid><wfw:comment>http://www.cppblog.com/SpringSnow/comments/68276.html</wfw:comment><comments>http://www.cppblog.com/SpringSnow/archive/2008/12/01/68276.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/SpringSnow/comments/commentRss/68276.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/SpringSnow/services/trackbacks/68276.html</trackback:ping><description><![CDATA[好文章，大家一起分享。<br><br>一直对extern "c"不是很明白。今天，看了一篇文章《C++中extern &#8220;C&#8221;含义深层探索》，对这个问题终于有所认识。转过来与大家分享。<br><br>链接：<a href="http://developer.51cto.com/art/200510/9066.htm">http://developer.51cto.com/art/200510/9066.htm</a><br>作者：宋宝华<br><br>
<p><strong>1.引言</strong><br>C++语言的创建初衷是&#8220;a better C&#8221;，但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同。作为一种欲与C兼容的语言，C++保留了一部分过程式语言的特点（被世人称为&#8220;不彻底地面向对象&#8221;），因而它可以定义不属于任何类的全局变量和函数。但是，C++毕竟是一种面向对象的程序设计语言，为了支持函数的重载，C++对全局函数的处理方式与C有明显的不同。<br><strong>2.从标准头文件说起<br></strong><br>某企业曾经给出如下的一道面试题：<br>面试题:为什么标准头文件都有类似以下的结构？ <br>#ifndef __INCvxWorksh<br>#define __INCvxWorksh <br>#ifdef __cplusplus<br>extern "C" {<br>#endif <br>/*...*/ <br>#ifdef __cplusplus<br>}<br>#endif <br>#endif /* __INCvxWorksh */<br>分析<br>显然，头文件中的编译宏&#8220;#ifndef __INCvxWorksh、#define __INCvxWorksh、#endif&#8221; 的作用是防止该头文件被重复引用。<br>那么<br>#ifdef __cplusplus<br>extern "C" {<br>#endif <br>#ifdef __cplusplus<br>}<br>#endif <br>的作用又是什么呢？我们将在下文一一道来。</p>
<p><strong>3.深层揭密extern "C"<br></strong><br>extern "C" 包含双重含义，从字面上即可得到：首先，被它修饰的目标是&#8220;extern&#8221;的；其次，被它修饰的目标是&#8220;C&#8221;的。让我们来详细解读这两重含义。<br>被extern "C"限定的函数或变量是extern类型的；<br>extern是C/C++语言中表明函数和全局变量作用范围（可见性）的关键字，该关键字告诉编译器，其声明的函数和变量可以在本模块或其它模块中使用。记住，下列语句：<br>extern int a;<br>仅仅是一个变量的声明，其并不是在定义变量a，并未为a分配内存空间。变量a在所有模块中作为一种全局变量只能被定义一次，否则会出现连接错误。<br>通常，在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如，如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样，模块B中调用模块A中的函数时，在编译阶段，模块B虽然找不到该函数，但是并不会报错；它会在连接阶段中从模块A编译生成的目标代码中找到此函数。<br>与extern对应的关键字是static，被它修饰的全局变量和函数只能在本模块中使用。因此，一个函数或变量只可能被本模块使用时，其不可能被extern &#8220;C&#8221;修饰。<br>被extern "C"修饰的变量和函数是按照C语言方式编译和连接的；<br>未加extern &#8220;C&#8221;声明时的编译方式<br>首先看看C++中对类似C的函数是怎样编译的。<br>作为一种面向对象的语言，C++支持函数重载，而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如，假设某个函数的原型为： <br>void foo( int x, int y );<br>该函数被C编译器编译后在符号库中的名字为_foo，而C++编译器则会产生像_foo_int_int之类的名字（不同的编译器可能生成的名字不同，但是都采用了相同的机制，生成的新名字称为&#8220;mangled name&#8221;）。<br>foo_int_int这样的名字包含了函数名、函数参数数量及类型信息，C++就是靠这种机制来实现函数重载的。例如，在C++中，函数void foo( int x, int y )与void foo( int x, float y )编译生成的符号是不相同的，后者为_foo_int_float。</p>
<p>同样地，C++中的变量除支持局部变量外，还支持类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名，我们以"."来区分。而本质上，编译器在进行编译时，与函数的处理相似，也为类中的变量取了一个独一无二的名字，这个名字与用户程序中同名的全局变量名字不同。<br>未加extern "C"声明时的连接方式<br>假设在C++中，模块A的头文件如下：<br>// 模块A头文件　moduleA.h<br>#ifndef MODULE_A_H<br>#define MODULE_A_H<br>int foo( int x, int y );<br>#endif<br>在模块B中引用该函数：<br>// 模块B实现文件　moduleB.cpp<br>#include "moduleA.h"<br>foo(2,3);</p>
<p>实际上，在连接阶段，连接器会从模块A生成的目标文件moduleA.obj中寻找_foo_int_int这样的符号！<br>加extern "C"声明后的编译和连接方式<br>加extern "C"声明后，模块A的头文件变为：<br>// 模块A头文件　moduleA.h<br>#ifndef MODULE_A_H<br>#define MODULE_A_H<br>extern "C" int foo( int x, int y );<br>#endif<br>在模块B的实现文件中仍然调用foo( 2,3 )，其结果是：<br>（1）模块A编译生成foo的目标代码时，没有对其名字进行特殊处理，采用了C语言的方式；<br>（2）连接器在为模块B的目标代码寻找foo(2,3)调用时，寻找的是未经修改的符号名_foo。<br>如果在模块A中函数声明了foo为extern "C"类型，而模块B中包含的是extern int foo( int x, int y ) ，则模块B找不到模块A中的函数；反之亦然。<br>所以，可以用一句话概括extern &#8220;C&#8221;这个声明的真实目的（任何语言中的任何语法特性的诞生都不是随意而为的，来源于真实世界的需求驱动。我们在思考问题时，不能只停留在这个语言是怎么做的，还要问一问它为什么要这么做，动机是什么，这样我们可以更深入地理解许多问题）：<br>实现C++与C及其它语言的混合编程。</p>
<p>明白了C++中extern "C"的设立动机，我们下面来具体分析extern "C"通常的使用技巧。</p>
<p><strong>4.extern "C"的惯用法</strong><br>（1）在C++中引用C语言中的函数和变量，在包含C语言头文件（假设为cExample.h）时，需进行下列处理：<br>extern "C"<br>{<br>#include "cExample.h"<br>}<br>而在C语言的头文件中，对其外部函数只能指定为extern类型，C语言中不支持extern "C"声明，在.c文件中包含了extern "C"时会出现编译语法错误。<br>笔者编写的C++引用C函数例子工程中包含的三个文件的源代码如下：<br>/* c语言头文件：cExample.h */<br>#ifndef C_EXAMPLE_H<br>#define C_EXAMPLE_H<br>extern int add(int x,int y);<br>#endif<br>/* c语言实现文件：cExample.c */<br>#include "cExample.h"<br>int add( int x, int y )<br>{<br>return x + y;<br>}<br>// c++实现文件，调用add：cppFile.cpp<br>extern "C" <br>{<br>#include "cExample.h"<br>}<br>int main(int argc, char* argv[])<br>{<br>add(2,3); <br>return 0;<br>}<br>如果C++调用一个C语言编写的.DLL时，当包括.DLL的头文件或声明接口函数时，应加extern "C" {　}。<br>（2）在C中引用C++语言中的函数和变量时，C++的头文件需添加extern "C"，但是在C语言中不能直接引用声明了extern "C"的该头文件，应该仅将C文件中将C++中定义的extern "C"函数声明为extern类型。</p>
<p>笔者编写的C引用C++函数例子工程中包含的三个文件的源代码如下：<br>//C++头文件 cppExample.h<br>#ifndef CPP_EXAMPLE_H<br>#define CPP_EXAMPLE_H<br>extern "C" int add( int x, int y );<br>#endif<br>//C++实现文件 cppExample.cpp<br>#include "cppExample.h"<br>int add( int x, int y )<br>{<br>return x + y;<br>}<br>/* C实现文件 cFile.c<br>/* 这样会编译出错：#include "cExample.h" */<br>extern int add( int x, int y );<br>int main( int argc, char* argv[] )<br>{<br>add( 2, 3 ); <br>return 0;<br>}<br>如果深入理解了第3节中所阐述的extern "C"在编译和连接阶段发挥的作用，就能真正理解本节所阐述的从C++引用C函数和C引用C++函数的惯用法。</p>
<img src ="http://www.cppblog.com/SpringSnow/aggbug/68276.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/SpringSnow/" target="_blank">Sandy</a> 2008-12-01 11:43 <a href="http://www.cppblog.com/SpringSnow/archive/2008/12/01/68276.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何添加代码注释</title><link>http://www.cppblog.com/SpringSnow/archive/2008/11/20/67354.html</link><dc:creator>Sandy</dc:creator><author>Sandy</author><pubDate>Thu, 20 Nov 2008 01:38:00 GMT</pubDate><guid>http://www.cppblog.com/SpringSnow/archive/2008/11/20/67354.html</guid><wfw:comment>http://www.cppblog.com/SpringSnow/comments/67354.html</wfw:comment><comments>http://www.cppblog.com/SpringSnow/archive/2008/11/20/67354.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/SpringSnow/comments/commentRss/67354.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/SpringSnow/services/trackbacks/67354.html</trackback:ping><description><![CDATA[如何添加代码注释？<br>这个我一直没有搞懂。自己随便涂鸦，也懒得加注释。但是真正参加项目，有时也会找理由不添注释。看了一些书，参加一些培训，有的人说，加注释好，有人说加注释不好。好有好的地方，坏也有坏的味道。对于我这个初来乍到之人来说，反而倒是非常迷惑。<br>最近看到一篇文章&#8220;添加代码注释13个技巧&#8221;，也解除了心中的部分疑团。贴在这里与大家分享，也备以后参考。<br>链接：<br><a href="http://sunxinhe.yo2.cn/articles/%E3%80%90%E8%BD%AC%E3%80%91%E6%B7%BB%E5%8A%A0%E4%BB%A3%E7%A0%81%E6%B3%A8%E9%87%8A13%E4%B8%AA%E6%8A%80%E5%B7%A7.html">http://sunxinhe.yo2.cn/articles/%E3%80%90%E8%BD%AC%E3%80%91%E6%B7%BB%E5%8A%A0%E4%BB%A3%E7%A0%81%E6%B3%A8%E9%87%8A13%E4%B8%AA%E6%8A%80%E5%B7%A7.html</a><br><br>添加代码注释13个技巧<br>
<p id=art style="MARGIN: 15px"><font size=2>作者：Jos&#233; M. Aguilar（西班牙语）<br>英文译者：Timm Martin<br>中文译者：numenzq</font></p>
<p><font size=2>下面的13个技巧向你展示如何添加代码注释，这些技巧都很容易理解和记忆。</font></p>
<p><font size=2><strong>1. 逐层注释<br></strong>为每个代码块添加注释，并在每一层使用统一的注释<span class="yo2keyword yo2keyword_tag"><a title="Tag 了 4 篇文章" href="http://sunxinhe.yo2.cn/articles/tag/%e6%96%b9%e6%b3%95"><u><font color=#0361a0>方法</font></u></a></span>和风格。例如：<br>针对每个类：包括摘要信息、作者信息、以及最近修改日期等<br>针对每个方法：包括用途、功能、参数和返回值等<br>在团队工作中，采用标准化的注释尤为重要。当然，使用注释规范和工具（例如<span class="yo2keyword yo2keyword_tag"><a title="Tag 了 2 篇文章" href="http://sunxinhe.yo2.cn/articles/tag/c"><u><font color=#0361a0>C</font></u></a></span>#里的XML，Java里的Javadoc）可以更好的推动注释工作完成得更好。<br><strong>2. 使用分段注释<br></strong>如果有多个代码块，而每个代码块完成一个单一任务，则在每个代码块前添加一个注释来向读者说明这段代码的功能。例子如下：</font></p>
<p><font size=2>// Check that all data records<br>// are correct<br>foreach (Record record in records)<br>{<br>if (rec.checkStatus()==Status.OK)<br>{<br>. . .<br>}<br>}<br>// Now we begin to perform<br>// transactions<br>Context ctx = new ApplicationContext();<br>ctx.BeginTransaction();<br>. . .</font></p>
<p><font size=2><strong>3. 在代码行后添加注释<br></strong>如果多行代码的每行都要添加注释，则在每行代码后添加该行的注释，这将很容易理解。例如：</font></p>
<p><font size=2>const MAX_ITEMS = 10; // maximum number of packets<br>const MASK = 0x1F;&nbsp;&nbsp;&nbsp; // mask bit TCP</font></p>
<p><font size=2>在分隔代码和注释时，有的<span class="yo2keyword yo2keyword_tag"><a title="Tag 了 1 篇文章" href="http://sunxinhe.yo2.cn/articles/tag/%e5%bc%80%e5%8f%91"><u><font color=#0361a0>开发</font></u></a></span>者使用tab键，而另一些则使用空格键。然而由于tab键在各编辑器和IDE工具之间的表现不一致，因此最好的方法还是使用空格键。</font></p>
<p><font size=2><strong>4. 不要侮辱读者的智慧</strong></font></p>
<p><font size=2>避免以下显而易见的注释：</font></p>
<p><font size=2>if (a == 5)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // if a equals 5<br>counter = 0; // set the counter to zero</font></p>
<p><font size=2>写这些无用的注释会浪费你的时间，并将转移读者对该代码细节的理解。</font></p>
<p><font size=2><strong>5. 礼貌点</strong><br>避免粗鲁的注释，如：&#8220;注意，愚蠢的使用者才会输入一个负数&#8221;或&#8220;刚修复的这个问题出于最初的无能开发者之手&#8221;。这样的注释能够反映到它的作者是多么的拙劣，你也永远不知道谁将会阅读这些注释，可能是：你的老板，客户，或者是你刚才侮辱过的无能开发者。</font></p>
<p><font size=2><strong>6. 关注要点</strong></font></p>
<p><font size=2>不要写过多的需要转意且不易理解的注释。避免ASCII艺术，搞笑，诗情画意，hyperverbosity的注释。简而言之，保持注释简单直接。</font></p>
<p><font size=2><strong>7. 使用一致的注释风格<br></strong>一些人坚信注释应该写到能被非编程者理解的程度。而其他的人则认为注释只要能 被开发人员理解就行了。无论如何，Successful Strategies for Commenting Code已经规定和阐述了注释的一致性和针对的读者。就个人而言，我怀疑大部分非编程人员将会去阅读代码，因此注释应该是针对其他的开发者而言。</font></p>
<p><font size=2><strong>8. 使用特有的标签<br></strong>在一个团队工作中工作时，为了便于与其它程序员沟通，应该采用一致的标签集进行注释。例如，在很多团队中用TODO标签表示该代码段还需要额外的工作。</font></p>
<p><font size=2>int Estimate(int x, int y)<br>{<br>// TODO: implement the calculations<br>return 0;<br>}</font></p>
<p><font size=2>注释标签切忌不要用于解释代码，它只是引起注意或传递信息。如果你使用这个技巧，记得追踪并确认这些信息所表示的是什么。</font></p>
<p><font size=2><strong>9. 在代码时添加注释</strong><br>在写代码时就添加注释，这时在你脑海里的是清晰完整的思路。如果在代码最后再添 加同样注释，它将多花费你一倍的时间。而&#8220;我没有时间写注释&#8221;，&#8220;我很忙&#8221;和&#8220;项目已经延期了&#8221;这都是不愿写注释而找的借口。一些开发者觉得应该 write comments before code，用于理清头绪。例如：<br>public void ProcessOrder()<br>{<br>// Make sure the products are available<br>// Check that the customer is valid<br>// Send the order to the store<br>// Generate bill<br>}</font></p>
<p><font size=2><strong>10. 为自己注释代码</strong></font></p>
<p><font size=2>当注释代码时，要考虑到不仅将来维护你代码的开发人员要看，而且你自己也可能要看。用Phil Haack大师的话来说就是：&#8220;一旦一行代码显示屏幕上，你也就成了这段代码的维护者&#8221;。因此，对于我们写得好（差）的注释而言，我们将是第一个受益者（受害者）。</font></p>
<p><font size=2><strong>11. 同时更新代码和注释</strong></font></p>
<p><font size=2>如果注释没有跟随代码的变化而变化，及时是正确的注释也没有用。代码和注释应该同步变化，否则这样的注释将对维护你代码的开发者带来更大的困难。使用重构工具时应特别注意，它只会自动更新代码而不会修改注释，因此应该立即停止使用重构工具。</font></p>
<p><font size=2><strong>12. 注释的黄金规则：易读的代码</strong><br>对于开发者的一个基本原则就是：让你的代码为己解释。虽然有些人怀疑这会让那些不愿意写注释的开发者钻空子，不过这样的代码真的会使你容易理解，还不需要额外维护注释。例如在Fluid Interfaces文章里向你展示的代码一样：</font></p>
<p><font size=2>Calculator calc = new Calculator();<br>calc.Set(0);<br>calc.Add(10);<br>calc.Multiply(2);<br>calc.Subtract(4);<br>Console.WriteLine( "Result: {0}", calc.Get() );</font></p>
<p><font size=2>在这个例子中，注释是不需要的，否则可能就违反了技巧4。为了使代码更容易理解，你可以考虑使用适当的名字 （Ottinger's Rules里讲解得相当好），确保正确的缩进，并且采用coding style guides，违背这个技巧可能的结果就像是注释在为不好的代码apologize。</font></p>
<p><font size=2><strong>13. 与同事分享技巧<br></strong>虽然技巧10已经向我们表明了我们是如何从好的注释中直接受益，这些技巧将让所有开发者受益，特别是团队中一起工作的同事。因此，为了编写出更容易理解和维护的代码，尝试自由的和你的同事分享这些注释技巧。<br></font></p>
<br>好东西拿出来一起分享<br>
<img src ="http://www.cppblog.com/SpringSnow/aggbug/67354.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/SpringSnow/" target="_blank">Sandy</a> 2008-11-20 09:38 <a href="http://www.cppblog.com/SpringSnow/archive/2008/11/20/67354.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>有意思的讨论：将ASSERT与正常程序混在一起好么？</title><link>http://www.cppblog.com/SpringSnow/archive/2008/11/04/65949.html</link><dc:creator>Sandy</dc:creator><author>Sandy</author><pubDate>Tue, 04 Nov 2008 10:28:00 GMT</pubDate><guid>http://www.cppblog.com/SpringSnow/archive/2008/11/04/65949.html</guid><wfw:comment>http://www.cppblog.com/SpringSnow/comments/65949.html</wfw:comment><comments>http://www.cppblog.com/SpringSnow/archive/2008/11/04/65949.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/SpringSnow/comments/commentRss/65949.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/SpringSnow/services/trackbacks/65949.html</trackback:ping><description><![CDATA[<div class=post>
<h2>下面摘自<a href="http://www.cppblog.com/woaidongmao/archive/2008/11/03/65897.html">http://www.cppblog.com/woaidongmao/archive/2008/11/03/65897.html</a></h2>
<h2>看到他们的在争论很有意思，我不是很懂。</h2>
<h2>有利还是有弊呢？</h2>
<h2><a id=viewpost1_TitleUrl href="http://www.cppblog.com/woaidongmao/archive/2008/11/03/65897.html"><font color=#223355><br>EXT_ASSERT将ASSERT与if结合在一起</font></a> </h2>
<div class=postbody>
<p>ASSERT在DEBUG程序时候帮了太多太多忙，不过在ASSERT判断传入参数后，还需要if再按相同条件判断一遍，不符合规则return，这样才是正确的逻辑。但这样代码难看，且工作重复无趣，又容易出现差漏。
<p>刚弄了个简单EXT_ASSERT宏，按我的理解应该可以解决问题，但不确定是否有漏洞，发出来大家一起瞄瞄。
<p>&nbsp;
<p>#define RET_VOID<br>#define EX_ASSERT(exp, ret) {ASSERT(exp);if(!(exp))return(ret);}
<p>&nbsp;
<p>BOOL CXXX::FunXXX(const data* p_data)<br>{<br>&nbsp;&nbsp; EXT_ASSERT(p_data, FALSE);//---- 返回BOOL型
<p>}
<p>int CXXX::FunXXX(const data* p_data)<br>{<br>&nbsp;&nbsp; EXT_ASSERT(p_data, -1);//---- 返回int型
<p>}</p>
<p>const retdata* CXXX::FunXXX(const data* p_data)<br>{<br>&nbsp;&nbsp;&nbsp; EXT_ASSERT(p_data, NULL);//---- 返回NULL指针
<p>}</p>
<p>retdata CXXX::FunXXX(const data* p_data)<br>{<br>&nbsp;&nbsp;&nbsp; EXT_ASSERT(p_data, retdata());//---- 返回空对象
<p>}</p>
<p>void CXXX::FunXXX(const data* p_data)<br>{<br>&nbsp;&nbsp;&nbsp; EXT_ASSERT(p_data, RET_VOID);//---- 仅仅return
<p>}</p>
</div>
<p class=postfoot>posted on 2008-11-03 23:34 <a href="http://www.cppblog.com/woaidongmao/"><font color=#223355>肥仔</font></a> 阅读(333) <a href="http://www.cppblog.com/woaidongmao/archive/2008/11/03/65897.html#Post"><font color=#223355>评论(7)</font></a> &nbsp;<a href="http://www.cppblog.com/woaidongmao/admin/EditPosts.aspx?postid=65897"><font color=#223355>编辑</font></a>&nbsp;<a href="http://www.cppblog.com/woaidongmao/AddToFavorite.aspx?id=65897"><font color=#223355>收藏</font></a> <a href="http://www.cppblog.com/woaidongmao/services/trackbacks/65897.aspx"><font color=#223355>引用</font></a> 所属分类: <a href="http://www.cppblog.com/woaidongmao/category/6005.html"><font color=#223355>C++存档</font></a> </p>
</div>
<img height=1 src="http://www.cppblog.com/woaidongmao/aggbug/65897.html?webview=1" width=1> <!--
<rdf:rdf xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:description
rdf:about="http://www.cppblog.com/woaidongmao/archive/2008/11/03/65897.html"
dc:identifier="http://www.cppblog.com/woaidongmao/archive/2008/11/03/65897.html"
dc:title="EXT_ASSERT将ASSERT与if结合在一起"
trackback:ping="http://www.cppblog.com/woaidongmao/services/trackbacks/65897.aspx" />
</rdf:rdf>
-->
<script type=text/javascript>
//<![cdata[
Sys.WebForms.PageRequestManager._initialize('AjaxHolder$scriptmanager1', document.getElementById('Form1'));
Sys.WebForms.PageRequestManager.getInstance()._updateControls(['tAjaxHolder$UpdatePanel1'], [], [], 90);
//]]&gt;
</script>
<div id=AjaxHolder_UpdatePanel1><a name=pagedcomment></a><a name=评论>
<div id=comments>
<h3>评论</h3>
<div class=post>
<h2><a title="permalink: re: EXT_ASSERT将ASSERT与if结合在一起" href="http://www.cppblog.com/woaidongmao/archive/2008/11/03/65897.html#65901">#</a><font color=#000000>&nbsp;</font><a name=65901></a><font color=#000000>re: EXT_ASSERT将ASSERT与if结合在一起&nbsp;&nbsp;</font><a onclick='return SetReplyAuhor("www.helpsoff.com.cn")' href="http://www.cppblog.com/woaidongmao/archive/2008/11/03/65897.html#post">回复</a><font color=#000000>&nbsp;&nbsp;</font><a title=查看该作者发表过的评论 href="http://www.cppblog.com/comment?author=www.helpsoff.com.cn" target=_blank>更多评论</a><font color=#000000> </font><a id=AjaxHolder_Comments_CommentList_ctl00_DeleteLink href="javascript:__doPostBack('AjaxHolder$Comments$CommentList$ctl00$DeleteLink','')"></a><font color=#000000>&nbsp;&nbsp;</font><a id=AjaxHolder_Comments_CommentList_ctl00_EditLink></a><font color=#000000> </font></h2>
哥们儿，如果你是说MFC里的ASSERT的话（看你的类命名风格，估计是吧），在retail build里，ASSERT是完全不会被放到代码里的。你这样用ASSERT，把ASSERT和if条件绑在一起就等于把处理错误的断言和正常程序逻辑绑在了一起，不是一个好的设计。如果一定要这么干，也该是绑VERIFY，至少在retail build里VERIFY里的逻辑还会被执行。<br><br>ASSERT应该拿来断言程序正常执行完全不可能出现的错误（这些错误会在debug build里出现是因为当前程序还不完善），在正常逻辑中，他们是不应该用程序逻辑去handle的错误，所以一句ASSERT够了。
<div class=postfoot>2008-11-04 05:27 | <a id=AjaxHolder_Comments_CommentList_ctl00_NameLink href="http://www.helpsoff.com.cn/" target=_blank><font color=#223355>www.helpsoff.com.cn</font></a> </div>
</div>
<div class=post>
<h2><a title="permalink: re: EXT_ASSERT将ASSERT与if结合在一起" href="http://www.cppblog.com/woaidongmao/archive/2008/11/03/65897.html#65916"><font color=#223355>#</font></a>&nbsp;<a name=65916></a>re: EXT_ASSERT将ASSERT与if结合在一起&nbsp;&nbsp;<a onclick='return SetReplyAuhor("肥仔")' href="http://www.cppblog.com/woaidongmao/archive/2008/11/03/65897.html#post"><font color=#223355>回复</font></a>&nbsp;&nbsp;<a title=查看该作者发表过的评论 href="http://www.cppblog.com/comment?author=%e8%82%a5%e4%bb%94" target=_blank><font color=#223355>更多评论</font></a> <a id=AjaxHolder_Comments_CommentList_ctl01_DeleteLink href="javascript:__doPostBack('AjaxHolder$Comments$CommentList$ctl01$DeleteLink','')"></a>&nbsp;&nbsp;<a id=AjaxHolder_Comments_CommentList_ctl01_EditLink></a> </h2>
@www.helpsoff.com.cn <br>我在Imperfect C++中看到过相同的言论。 <br>不过我的应用是，常常用ASSERT检测参数的合法性，ASSERT之后，当然还要if一把了，对于ASSERT和if不要放在一起这种观点，我不是很认同，我觉得放在一起很好用的。 <br><br>另外，在Release下，ASSERT没了，但是if留下了，这是需要的效果。 <br>
<div class=postfoot>2008-11-04 10:45 | <a id=AjaxHolder_Comments_CommentList_ctl01_NameLink href="http://www.cppblog.com/woaidongmao/" target=_blank><font color=#223355>肥仔</font></a> </div>
</div>
<div class=post>
<h2><a title="permalink: re: EXT_ASSERT将ASSERT与if结合在一起" href="http://www.cppblog.com/woaidongmao/archive/2008/11/03/65897.html#65919"><font color=#223355>#</font></a>&nbsp;<a name=65919></a>re: EXT_ASSERT将ASSERT与if结合在一起&nbsp;&nbsp;<a onclick='return SetReplyAuhor("Touchsoft")' href="http://www.cppblog.com/woaidongmao/archive/2008/11/03/65897.html#post"><font color=#223355>回复</font></a>&nbsp;&nbsp;<a title=查看该作者发表过的评论 href="http://www.cppblog.com/comment?author=Touchsoft" target=_blank><font color=#223355>更多评论</font></a> <a id=AjaxHolder_Comments_CommentList_ctl02_DeleteLink href="javascript:__doPostBack('AjaxHolder$Comments$CommentList$ctl02$DeleteLink','')"></a>&nbsp;&nbsp;<a id=AjaxHolder_Comments_CommentList_ctl02_EditLink></a> </h2>
我不会这么用，断言的目的去那了。
<div class=postfoot>2008-11-04 11:30 | <a id=AjaxHolder_Comments_CommentList_ctl02_NameLink target=_blank><font color=#223355>Touchsoft</font></a> </div>
</div>
<div class=post>
<h2><a title="permalink: re: EXT_ASSERT将ASSERT与if结合在一起" href="http://www.cppblog.com/woaidongmao/archive/2008/11/03/65897.html#65922"><font color=#223355>#</font></a>&nbsp;<a name=65922></a>re: EXT_ASSERT将ASSERT与if结合在一起&nbsp;&nbsp;<a onclick='return SetReplyAuhor("www.helpsoff.com.cn")' href="http://www.cppblog.com/woaidongmao/archive/2008/11/03/65897.html#post"><font color=#223355>回复</font></a>&nbsp;&nbsp;<a title=查看该作者发表过的评论 href="http://www.cppblog.com/comment?author=www.helpsoff.com.cn" target=_blank><font color=#223355>更多评论</font></a> <a id=AjaxHolder_Comments_CommentList_ctl03_DeleteLink href="javascript:__doPostBack('AjaxHolder$Comments$CommentList$ctl03$DeleteLink','')"></a>&nbsp;&nbsp;<a id=AjaxHolder_Comments_CommentList_ctl03_EditLink></a> </h2>
@肥仔<br>哥们儿，你还是没理解，ASSERT的不是拿来干这个的。你爱怎样玩就怎样玩吧，反正自己的代码自己维护，其他人的意见听不听在你。
<div class=postfoot>2008-11-04 12:29 | <a id=AjaxHolder_Comments_CommentList_ctl03_NameLink href="http://www.helpsoff.com.cn/" target=_blank><font color=#223355>www.helpsoff.com.cn</font></a> </div>
</div>
<div class=post>
<h2><a title="permalink: re: EXT_ASSERT将ASSERT与if结合在一起" href="http://www.cppblog.com/woaidongmao/archive/2008/11/03/65897.html#65925"><font color=#223355>#</font></a>&nbsp;<a name=65925></a>re: EXT_ASSERT将ASSERT与if结合在一起&nbsp;&nbsp;<a onclick='return SetReplyAuhor("肥仔")' href="http://www.cppblog.com/woaidongmao/archive/2008/11/03/65897.html#post"><font color=#223355>回复</font></a>&nbsp;&nbsp;<a title=查看该作者发表过的评论 href="http://www.cppblog.com/comment?author=%e8%82%a5%e4%bb%94" target=_blank><font color=#223355>更多评论</font></a> <a id=AjaxHolder_Comments_CommentList_ctl04_DeleteLink href="javascript:__doPostBack('AjaxHolder$Comments$CommentList$ctl04$DeleteLink','')"></a>&nbsp;&nbsp;<a id=AjaxHolder_Comments_CommentList_ctl04_EditLink></a> </h2>
@www.helpsoff.com.cn <br>谢谢你的意见，但是不采纳。原因有3点经历： <br><br>1、ASSERT判断函数参数合法性，调试时会帮了很大的忙； <br>2、if判段函数参数合法性，是健壮性的一部分； <br>3、ASSERT和if 合在一起，不觉得有任何不妥，且ASSERT不出现在Release中，这正是需要的。 <br><br>可能涉及到的一个争论是，检测参数合法形是调用者，还是被调用者的责任？ <br>C/C++的主流是调用者保证参数的合法性，被调用者不检测参数合法性，这就是为什么认为，只要ASSERT，不需要if了。 <br>strcpy(szBuf, NULL)之所以让一个程序崩溃也是这个原因，但是为什么要让它崩溃？能够不崩溃，继续执行岂不是更好吗？ <br>
<div class=postfoot>2008-11-04 13:44 | <a id=AjaxHolder_Comments_CommentList_ctl04_NameLink href="http://www.cppblog.com/woaidongmao/" target=_blank><font color=#223355>肥仔</font></a> </div>
</div>
<div class=post>
<h2><a title="permalink: re: EXT_ASSERT将ASSERT与if结合在一起" href="http://www.cppblog.com/woaidongmao/archive/2008/11/03/65897.html#65934"><font color=#223355>#</font></a>&nbsp;<a name=65934></a>re: EXT_ASSERT将ASSERT与if结合在一起&nbsp;&nbsp;<a onclick='return SetReplyAuhor("www.helpsoff.com.cn")' href="http://www.cppblog.com/woaidongmao/archive/2008/11/03/65897.html#post"><font color=#223355>回复</font></a>&nbsp;&nbsp;<a title=查看该作者发表过的评论 href="http://www.cppblog.com/comment?author=www.helpsoff.com.cn" target=_blank><font color=#223355>更多评论</font></a> <a id=AjaxHolder_Comments_CommentList_ctl05_DeleteLink href="javascript:__doPostBack('AjaxHolder$Comments$CommentList$ctl05$DeleteLink','')"></a>&nbsp;&nbsp;<a id=AjaxHolder_Comments_CommentList_ctl05_EditLink></a> </h2>
1) 没人否认ASSERT的用处；<br>2) 需要if判断处理的参数和用ASSERT断言的不合法参数，不应属于一个范畴，不应该混合在一起处理；<br>3) 代码不管怎么写在没遇到问题前都不会有什么不妥，自己觉得好就好吧。<br><br>你当然可以去写一个万能的strcpy，但是如何能保证你的strcpy是真正的&#8220;万能&#8221;的呢？不崩溃继续执行倒是没问题，但是出问题的真正根源在哪里呢，你这样做不就掩盖了问题吗？应该做的是出现这样的问题时，能有用且有效的指出错误，而不是做garbage in, garbage out。<br><br>设计代码，不去扯那些玩得出花花的设计模式，有些很基本很直白的原则，比如说&#8220;garbage in, garbage out&#8221;，比如高内聚／低耦合...说多了也没意思，楼主爱怎么玩怎么玩，大家都是这么过来的，其中的东西自己去体会了。
<div class=postfoot>2008-11-04 15:35 | <a id=AjaxHolder_Comments_CommentList_ctl05_NameLink href="http://www.helpsoff.com.cn/" target=_blank><font color=#223355>www.helpsoff.com.cn</font></a> </div>
</div>
<div class=post>
<h2><a title="permalink: re: EXT_ASSERT将ASSERT与if结合在一起" href="http://www.cppblog.com/woaidongmao/archive/2008/11/03/65897.html#65942"><font color=#223355>#</font></a>&nbsp;<a name=65942></a>re: EXT_ASSERT将ASSERT与if结合在一起<a name=Post></a>&nbsp;&nbsp;<a onclick='return SetReplyAuhor("肥仔")' href="http://www.cppblog.com/woaidongmao/archive/2008/11/03/65897.html#post"><font color=#223355>回复</font></a>&nbsp;&nbsp;<a title=查看该作者发表过的评论 href="http://www.cppblog.com/comment?author=%e8%82%a5%e4%bb%94" target=_blank><font color=#223355>更多评论</font></a> <a id=AjaxHolder_Comments_CommentList_ctl06_DeleteLink href="javascript:__doPostBack('AjaxHolder$Comments$CommentList$ctl06$DeleteLink','')"></a>&nbsp;&nbsp;<a id=AjaxHolder_Comments_CommentList_ctl06_EditLink></a> </h2>
@www.helpsoff.com.cn <br>程序以外，人生很多地方都需要与别人探讨，对于不合己见者，请不必太在怀，更没必要带着情绪和语气，摆出姿态。这样才能赢得更多的合作，我想我的这几句话还算中肯。 <br>
<div class=postfoot>2008-11-04 16:32 | <a id=AjaxHolder_Comments_CommentList_ctl06_NameLink href="http://www.cppblog.com/woaidongmao/" target=_blank><font color=#223355>肥仔</font></a> </div>
</div>
</div>
</div>
<img src ="http://www.cppblog.com/SpringSnow/aggbug/65949.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/SpringSnow/" target="_blank">Sandy</a> 2008-11-04 18:28 <a href="http://www.cppblog.com/SpringSnow/archive/2008/11/04/65949.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Essential C++ 学习——异常异常处理（一）</title><link>http://www.cppblog.com/SpringSnow/archive/2008/11/03/65833.html</link><dc:creator>Sandy</dc:creator><author>Sandy</author><pubDate>Mon, 03 Nov 2008 05:35:00 GMT</pubDate><guid>http://www.cppblog.com/SpringSnow/archive/2008/11/03/65833.html</guid><wfw:comment>http://www.cppblog.com/SpringSnow/comments/65833.html</wfw:comment><comments>http://www.cppblog.com/SpringSnow/archive/2008/11/03/65833.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/SpringSnow/comments/commentRss/65833.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/SpringSnow/services/trackbacks/65833.html</trackback:ping><description><![CDATA[<p>练习一<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 以下函数完全没有检查可能的数据错误以及可能的执行失败。请指出此函数中所有可能发生错误的地方。本题并不考虑出现异常。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int *alloc_and_init(string file_name)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ifstream infile(file_name);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int elem_cnt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;infile &gt;&gt; elem_cnt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int *pi = allocate_array(elem_cnt);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int elem;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int index = 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(infile &gt;&gt; elem)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pi[index++] = elem;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sort_array(pi, elem_cnt);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;register_data(pi);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return pi;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>这是书中第203页的练习7.1。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我自己的答案：打开文件后，未对infile进行判断，是否打开文件成功；pi是否分配成功，未进行判断，它是否为null。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 侯捷老师给的答案如下：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第一个错误便是&#8220;型别不符&#8221;。ifstream constructor 接受的参数型别是const char*而非string。这个没有注意到。解决方法是利用string的c_str member function取得其c-style字符串表现形式：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ifstream infile(file_name.c_str());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第二个错误是检查infile是否成功开启。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; ( !infile ) // 开启失败<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第三个错误就是infile &gt;&gt; elem_cnt 可能执行失败。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如，文件内含的是文字，那么企图&#8220;读入某个数值并置于elem_cnt内&#8221;的操作便告失败。此外，文件也有可能是空的。必须检查读取是否成功。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; infile &gt;&gt; elem_cnt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (! infile) // 读取失败<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;第四个错误int *pi = allocate_array(elem_cnt);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无论何时，当我们处理指针时，必须随时注意指针是否的确指向实际存在的对象。如果allocate_array()无法配置足够内存，pi便会被设为0，我们必须检验如下：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; ( ! pi ) // allocate_array() 没有配置到内存<br><br>&nbsp;需要说明的是：程序的假设是（1）elem_cnt代表文件中的元素个数；（2）数组索引值index绝不会发生溢出。但是除非我们检查，否则实在无法保证index永远不大于elem_cnt。<br><br>第一个错误和第三个错误，没有考虑到。分析看，对于&#8220;型别不符&#8221;这个问题，一直没有注意到。此外，对于读入文字，没有思考那么多。<br><br>努力学习ing&#8230;&#8230;</p>
<img src ="http://www.cppblog.com/SpringSnow/aggbug/65833.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/SpringSnow/" target="_blank">Sandy</a> 2008-11-03 13:35 <a href="http://www.cppblog.com/SpringSnow/archive/2008/11/03/65833.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>