﻿<?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++ language</title><link>http://www.cppblog.com/llface/category/441.html</link><description>碗里只剩馊泡面，地下皆为臭袜子；
墙上满是浑沌色，箱中却成蝼蚁窝。
</description><language>zh-cn</language><lastBuildDate>Fri, 23 May 2008 18:36:23 GMT</lastBuildDate><pubDate>Fri, 23 May 2008 18:36:23 GMT</pubDate><ttl>60</ttl><item><title>剖析ActiveX控件安全问题</title><link>http://www.cppblog.com/llface/articles/ActiveXSafe.html</link><dc:creator>西山居士</dc:creator><author>西山居士</author><pubDate>Sun, 30 Apr 2006 04:29:00 GMT</pubDate><guid>http://www.cppblog.com/llface/articles/ActiveXSafe.html</guid><wfw:comment>http://www.cppblog.com/llface/comments/6479.html</wfw:comment><comments>http://www.cppblog.com/llface/articles/ActiveXSafe.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/llface/comments/commentRss/6479.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/llface/services/trackbacks/6479.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Dissect ActiveX Control Safety																																																												1、介绍 		　如果你曾经在网页或者ASP中使用过com对象，你可能会发现，有时候会出现这样讨厌的对话框 															...&nbsp;&nbsp;<a href='http://www.cppblog.com/llface/articles/ActiveXSafe.html'>阅读全文</a><img src ="http://www.cppblog.com/llface/aggbug/6479.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/llface/" target="_blank">西山居士</a> 2006-04-30 12:29 <a href="http://www.cppblog.com/llface/articles/ActiveXSafe.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>翻译] 对话：换个名字(0011)</title><link>http://www.cppblog.com/llface/articles/2131.html</link><dc:creator>西山居士</dc:creator><author>西山居士</author><pubDate>Mon, 26 Dec 2005 05:51:00 GMT</pubDate><guid>http://www.cppblog.com/llface/articles/2131.html</guid><wfw:comment>http://www.cppblog.com/llface/comments/2131.html</wfw:comment><comments>http://www.cppblog.com/llface/articles/2131.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/llface/comments/commentRss/2131.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/llface/services/trackbacks/2131.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 原文地址：http://www.cuj.com/documents/s=8001/cujcexp1811hyslop/********************************************************************对话：换了名字-----------------------------------------------仅仅挂起100公里的距离，小行星就...&nbsp;&nbsp;<a href='http://www.cppblog.com/llface/articles/2131.html'>阅读全文</a><img src ="http://www.cppblog.com/llface/aggbug/2131.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/llface/" target="_blank">西山居士</a> 2005-12-26 13:51 <a href="http://www.cppblog.com/llface/articles/2131.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[翻译]对话：究竟谁才是可移植的程序员？(0009)</title><link>http://www.cppblog.com/llface/articles/1399.html</link><dc:creator>西山居士</dc:creator><author>西山居士</author><pubDate>Tue, 29 Nov 2005 04:22:00 GMT</pubDate><guid>http://www.cppblog.com/llface/articles/1399.html</guid><wfw:comment>http://www.cppblog.com/llface/comments/1399.html</wfw:comment><comments>http://www.cppblog.com/llface/articles/1399.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/llface/comments/commentRss/1399.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/llface/services/trackbacks/1399.html</trackback:ping><description><![CDATA[<P>原文地址：<A href="http://www.cuj.com/documents/s=8003/cujcexp1809sutter/">http://www.cuj.com/documents/s=8003/cujcexp1809sutter/</A><BR>********************************************************************<BR><BR>Jim Hyslop &nbsp;&nbsp;Herb Sutter</P>
<P>“嗨，小鬼。”Jeannine走过来坐在我对面，我现在很邋遢。“听说消息了吗？”<BR>我扫了一眼时间确认一下，我并不打算再跟她聊半个小时以上。“嗨，二等公民。不，还不是。无论如何，他们仍在值班。你今天这么早就不值班了？”<BR>“Brzenkowski睡不着，所以他跟我换班了。我欠了他一次。”<BR>“他真体贴，”我又吃了一口午餐同意道，“我真的很喜欢他，他经常加班，而且并不会影响到其他人，他知道如何融入到这个环境中来。但愿我们在下个月的行星登陆（planetfall）以后还能与他一起工作。任何人都该如此专业。”<BR>“大多数人都是的，”Jeannine笑了。“你自己也不赖阿。”<BR>“实际上，”我咯咯笑了笑，“你让我想起了bob。你知道，我以前跟你提过他，他是我第一次工作遇到的另一个怪人。哥们，有时他做起事情来能让你把肺气炸。因此如果有人默不作声的工作，我们都叫他‘胡扯Bob'”<BR>我继续讲述我的故事...<BR>---------------------------------------------<BR>一个声音在我耳边响起：“嘿，新来的，你破坏了结构。”<BR>我暗暗叹了口气，然后闭上了我的眼睛。我做这份工作已经快2个月了，我早就开始讨厌Guru叫我‘我的学徒’，但也不及这个没用的程序员Bob这样叫我-尤其是“新来的”。我数到10，然后直直的回答：“Bob，你在说什么？”<BR>“你的新代码check in了，”Bob温和地回复，吸了口他的拿铁咖啡（latté）。“我的编译器不能通过。它在抱怨一个迭代器已经定义过了。你破坏了结构，朋友。在头儿发现之前赶紧改掉把。”我缩了一下，我还不熟练，我知道破坏结构是很糟糕的事情。我甚至可以想象到Guru知道后的反应：记住，我的小学徒，团队合作的第二条戒律就是绝对不要破坏结构。<BR>“好吧，”我又叹了口气，这次乖了。“你在说代码的哪个部分？”<BR>Bob弯下身，打了几个键，弄出了下面的函数：</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: #008000">//</SPAN><SPAN style="COLOR: #008000">OBJMAP是一种标准容器的typedef</SPAN><SPAN style="COLOR: #008000"><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;f(OBJMAP&nbsp;</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">theMap)<BR><IMG id=Codehighlighter1_47_290_Open_Image onclick="this.style.display='none'; Codehighlighter1_47_290_Open_Text.style.display='none'; Codehighlighter1_47_290_Closed_Image.style.display='inline'; Codehighlighter1_47_290_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_47_290_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_47_290_Closed_Text.style.display='none'; Codehighlighter1_47_290_Open_Image.style.display='inline'; Codehighlighter1_47_290_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_47_290_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_47_290_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">(OBJMAP::iterator&nbsp;iter&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;theMap.begin();<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iter&nbsp;</SPAN><SPAN style="COLOR: #000000">!=</SPAN><SPAN style="COLOR: #000000">&nbsp;theMap.end();<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #000000">++</SPAN><SPAN style="COLOR: #000000">iter)<BR><IMG id=Codehighlighter1_135_154_Open_Image onclick="this.style.display='none'; Codehighlighter1_135_154_Open_Text.style.display='none'; Codehighlighter1_135_154_Closed_Image.style.display='inline'; Codehighlighter1_135_154_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_135_154_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_135_154_Closed_Text.style.display='none'; Codehighlighter1_135_154_Open_Image.style.display='inline'; Codehighlighter1_135_154_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;</SPAN><SPAN id=Codehighlighter1_135_154_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_135_154_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">do&nbsp;something</SPAN><SPAN style="COLOR: #008000"><BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top></SPAN><SPAN style="COLOR: #000000">&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">other&nbsp;code&nbsp;in&nbsp;here</SPAN><SPAN style="COLOR: #008000"><BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top></SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">(OBJMAP::iterator&nbsp;iter&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;theMap.begin();<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iter&nbsp;</SPAN><SPAN style="COLOR: #000000">!=</SPAN><SPAN style="COLOR: #000000">&nbsp;theMap.end();<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #000000">++</SPAN><SPAN style="COLOR: #000000">iter)<BR><IMG id=Codehighlighter1_264_288_Open_Image onclick="this.style.display='none'; Codehighlighter1_264_288_Open_Text.style.display='none'; Codehighlighter1_264_288_Closed_Image.style.display='inline'; Codehighlighter1_264_288_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_264_288_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_264_288_Closed_Text.style.display='none'; Codehighlighter1_264_288_Open_Image.style.display='inline'; Codehighlighter1_264_288_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;</SPAN><SPAN id=Codehighlighter1_264_288_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_264_288_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">do&nbsp;something&nbsp;else</SPAN><SPAN style="COLOR: #008000"><BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top></SPAN><SPAN style="COLOR: #000000">&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN></DIV>
<P>“这里有错误吗？”我问道。“我在Stroustrup里把它check out了，迭代器应该在每一个循环结束时超出了范围。”<BR>“是啊，是要这样的，但我的编译器不支持。”Bob回答说，剔着自己的牙齿。“它抱怨说iter已经定义了。很容易的更改吧，仅仅只是去掉iter的第二次定义。实际上，当我check in 它的时候，那就是我的代码起始如何读进去的。然后你的代码运行的时候破坏了结构。”<BR>我终于明白了。由于我仍在在试用期，我不得不表现得很谦逊。“Bob，”我心有成竹，“这是必须在我们面对的所有平台上面编译的。我把第二个定义放上是因为我的编译器抱怨第二个迭代器没有定义，根据Stroustrup，他应该能工作。”<BR>Bob似乎有些不耐烦。“我不在乎你的新编译器。我用我的很多年了，它从没有让我失望过。你的代码不能工作。”<BR>“Bob，代码是正确的。在我这里编译没问题。”<BR>“你的是个烂编译器。不是我的错，我在做我的工作，我不在乎别的编译器。”Bob又耸了耸肩，为自己辩护道。<BR>一个响亮的声音在我们身后响起：“我感觉你有些害怕阿。”<BR>我吓了一跳；Bob也好不到哪里，拿铁咖啡还在乱晃。Guru无声的在我们身后定住，手里还是拿着一本厚厚的书。<BR>Guru慢慢的摇了摇头，皱了皱眉毛。“害怕导致愤怒。”她继续说道。<BR>“哼，住口。我不担心别的编译器！”Bob激动的说，吸着溅落在他手上的奶咖啡。“我一点也不在乎它们。”<BR>“愤怒导致仇恨。仇恨...导致苦难。”<BR>“我是在受苦，没错，”我大气不敢喘，小声地嘀咕了声。“我只是想写出可移植的代码。-好吧，Bob，”我认输了，渴望摆脱掉他，“我会改掉它让它好好工作的，好吗？”<BR>“就像我说的，新来的，去掉第二个声明就可以了。”他又看了看我，然后转过身走了。<BR>Wendy靠着下一个隔间，看着他走了。“那么这次Bahb又在抱怨什么呢？”她问我。然后Guru靠近站了站，合上了她那本厚书，我给Wendy看了那段代码，解释了一下Bob要做的。“真是典型，”Wendy有点生气，“在实现一个可移植的方案和依赖于他的编译器的方案之间选择的话，他会毫不犹豫选择后者。就像你说的，他的代码不具有可移植性。你知道，这样的话，你就真的不需要在每个循环声明一个新的迭代器。只在第一个循环之前声明它们一次，它们就可以在两种编译器下都良好工作。”她快速改变了一下那段代码：</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: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;OBJMAP&nbsp;is&nbsp;a&nbsp;typedef&nbsp;for&nbsp;a&nbsp;standard&nbsp;container</SPAN><SPAN style="COLOR: #008000"><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;f(OBJMAP&nbsp;</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">theMap)<BR><IMG id=Codehighlighter1_71_353_Open_Image onclick="this.style.display='none'; Codehighlighter1_71_353_Open_Text.style.display='none'; Codehighlighter1_71_353_Closed_Image.style.display='inline'; Codehighlighter1_71_353_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_71_353_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_71_353_Closed_Text.style.display='none'; Codehighlighter1_71_353_Open_Image.style.display='inline'; Codehighlighter1_71_353_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_71_353_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_353_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;OBJMAP::iterator&nbsp;iter;<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;iter&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;theMap.begin();<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iter&nbsp;</SPAN><SPAN style="COLOR: #000000">!=</SPAN><SPAN style="COLOR: #000000">&nbsp;theMap.end();<BR><IMG id=Codehighlighter1_181_211_Open_Image onclick="this.style.display='none'; Codehighlighter1_181_211_Open_Text.style.display='none'; Codehighlighter1_181_211_Closed_Image.style.display='inline'; Codehighlighter1_181_211_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_181_211_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_181_211_Closed_Text.style.display='none'; Codehighlighter1_181_211_Open_Image.style.display='inline'; Codehighlighter1_181_211_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #000000">++</SPAN><SPAN style="COLOR: #000000">iter&nbsp;)&nbsp;</SPAN><SPAN id=Codehighlighter1_181_211_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_181_211_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: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;do&nbsp;something</SPAN><SPAN style="COLOR: #008000"><BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top></SPAN><SPAN style="COLOR: #000000">&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: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;other&nbsp;code&nbsp;in&nbsp;here</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">for</SPAN><SPAN style="COLOR: #000000">(&nbsp;iter&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;theMap.begin();<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iter&nbsp;</SPAN><SPAN style="COLOR: #000000">!=</SPAN><SPAN style="COLOR: #000000">&nbsp;theMap.end();<BR><IMG id=Codehighlighter1_320_351_Open_Image onclick="this.style.display='none'; Codehighlighter1_320_351_Open_Text.style.display='none'; Codehighlighter1_320_351_Closed_Image.style.display='inline'; Codehighlighter1_320_351_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_320_351_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_320_351_Closed_Text.style.display='none'; Codehighlighter1_320_351_Open_Image.style.display='inline'; Codehighlighter1_320_351_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #000000">++</SPAN><SPAN style="COLOR: #000000">iter&nbsp;)&nbsp;</SPAN><SPAN id=Codehighlighter1_320_351_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_320_351_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: #008000">//</SPAN><SPAN style="COLOR: #008000">&nbsp;do&nbsp;something&nbsp;else</SPAN><SPAN style="COLOR: #008000"><BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top></SPAN><SPAN style="COLOR: #000000">&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></DIV>
<P>Guru检查了一下自己的书写，扫了一眼这个方案。“非常聪明，孩子。”Wendy轻挑眉梢：她常常这样。“而且如你所说，这不是惟一的方案。另一个优雅的可能是干脆避免迭代器的声明，也许提高了可读性，通过在可能的地方使用for_each和模板表达式。我的学徒。”Guru继续对我说，“但是了解，理解和遵守神圣标准是很重要的，了解你的工具甚至那些不正常的也很重要。Bob在使用的那个编译器不服从for初始化变量的范围。他不在乎可移植的代码，只在乎自己的编译器。”<BR>“嗯...”我说，摸了摸自己的下巴。“写可移植的代码比我想的要困难，所以，在我们可以利用我原先的代码前，不得不等着Bob的编译器出新的版本了。”<BR>Guru注视着自己前方好一会。“我不是先知，我看不到未来。虽然如此，我还是能看到：可移植的发布绝对不会消失。编译器不都是遵守标准的-只是在级别上保持一致罢了。一些开发商甚至已经在他们的编译器里摒弃了过时的行为，而并不是一味迎合旧代码。<BR>“而且，一些编译器会产生出新的特性来扩展标准。有一些是很好的，还有一些会使语言趋于陈腐，没有弹性，最终会亡于停步不前。只适应一个平台的程序可能从新特性中获益。在可移植代码中使用那些非标准的特性有时是灾难性的-有些见习生，比如你，可能不注意他们的不可移植性而滥用它们。不要只钟爱于某一个编译器而害怕其他的。害怕就要导致不能移植。”<BR>她停了一下，然后转身走了。随着她的离开，她绵绵的声线飘入我们的耳朵，“但愿我能记起那位圣人的名字，他曾经说过，‘理论和实践的区别总是在实践中更明显...’”<BR>-----------------------------------------------------<BR>“Bob并不是一个融入大局的家伙，”我总结道。<BR>“在Ganymede号上没有人是这样的，”Jeannine也同意。“这并不是一个可以原谅的地方。嘿，你得走了。Anderson在等你。”<BR>我看了看时间站了起来。“职责呼叫。在第三次调查后你和Laura在做什么？”我问，因为我发现了那儿，当然，还有比谈论Bob更舒适的事情，比如Guru...</P><img src ="http://www.cppblog.com/llface/aggbug/1399.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/llface/" target="_blank">西山居士</a> 2005-11-29 12:22 <a href="http://www.cppblog.com/llface/articles/1399.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[翻译] 对话：接触指针(0207)</title><link>http://www.cppblog.com/llface/articles/1366.html</link><dc:creator>西山居士</dc:creator><author>西山居士</author><pubDate>Mon, 28 Nov 2005 08:32:00 GMT</pubDate><guid>http://www.cppblog.com/llface/articles/1366.html</guid><wfw:comment>http://www.cppblog.com/llface/comments/1366.html</wfw:comment><comments>http://www.cppblog.com/llface/articles/1366.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/llface/comments/commentRss/1366.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/llface/services/trackbacks/1366.html</trackback:ping><description><![CDATA[<P>原文地址：<BR><A href="http://www.cuj.com/documents/s=7981/cujcexp2007hyslop/">http://www.cuj.com/documents/s=7981/cujcexp2007hyslop/</A><BR>欢迎朋友们批评指正。<BR><BR>***************************************************************************************<BR>Jim Hyslop&nbsp;&nbsp;&nbsp;&nbsp; Herb Sutter<BR>---------------------------------------<BR>Copyright 2002, Jim Hyslop and Herb Sutter</P>
<P>“哎呀！”<BR>这是我一小时内第七次受挫了。显然Wendy很讨厌我这样。“看就看吧，朋友，安静一会行不行？”她的声音飘出了隔间。貌似比她先前的反应好些。<BR>我正是在auto_ptrs这里摔跤了。在为Guru工作的前些天里，我已经了解了auto_ptrs的好处-以及他们并不很明显的缺陷。我已经被auto_ptrs的奇怪的所有权语义刺痛了。auto_ptr是用move操作来代替copy操作，想象一下：当你走近一台影印机，把材料放进进纸器，按下“Copy”按钮。几分钟之后，影印机给了你一份拷贝-然后把原文扔进了碎纸机。这正好和auto_ptr的拷贝和赋值做的一样。<BR>总之，虽然我很聪明还有更多的经验，我仍然撞在了auto_ptr的各种限制上面。auto_ptr不能持有指向数组的指针， 我打算通过以下删除数组的方式来玩玩它：</P>
<P></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">auto_ptr</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;autoArray(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;T[</SPAN><SPAN style="COLOR: #000000">10</SPAN><SPAN style="COLOR: #000000">]);<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #008000">//...</SPAN><SPAN style="COLOR: #008000"><BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #000000">delete&nbsp;[]&nbsp;autoArray.release();</SPAN></DIV>
<P>但是我几乎马上抛弃了这个主意。甚至我可以看到这个“憎恶（abomination）（正如Guru说的）”的很多危害。全部的，恩，全部的auto_ptr的要点都是用于拥有和销毁内存的；要是手动处理就完全违背了其目的。<BR>因此我决定使用vector来取代拥有一个array， 这将比我需要的更强大，因为我不需要vector的动态调整大小，但它却符合我的目的。我真正想要的是一个能自动持有指针和内存管理权的智能指针，来让我可以用来操作一个数组。</P>
<P>“使用Boost， Luke，”我听到了背后Guru的声音。<BR>“不是“使用Force，Luke”吗？”我耸耸肩，“还有，不要叫我Luke。”<BR>“Boost库将是一个强大的支持，”Guru继续她的完美表演。<BR>虽然我今天不在状态，但我仍打断了她。“阿，我们今天能不能不要表演了？Bob在我们伦敦的办公室，没有实习医生可以处理反常者了。”<BR>她来到我旁边，我看到她笑着耸了耸肩，“哦，我刚才觉得很无聊，”她叹了口气，“你检验过Boost库的智能指针了吗？”<BR>“唔，好吧，”我犹豫了，“我还没机会看Boost库的细节。使用智能指针方法的都有什么？”<BR>“总共有5种，”Guru坐下后说。“2个提供了简单指针所有权，2个共享所有权。”<BR>“共享所有权？哦，就是说像一个引用技术类咯？”<BR>“没错，智能指针是成对的，所以你有一个持有指向简单对象的指针的智能指针的时候，还有一个持有指向数组的指针。”她突然停住了，开始在白板上写下了：scoped_ptr, scoped_array, shared_ptr, shared_array。<BR>“这只有4个；你不是说有5个吗？”我质问。<BR>“还有一个是weak_ptr。它是shared_ptr的一个无所有权的观察者。我待会会说到这个。scoped_* 指针自动销毁超出作用区域的对象， 一种建议的用法就是实现出Pimpl-指向实现的，”她一口气说完，阻止了我另一次的双关语。<BR>“那么。。。他们都像auto_ptr，对吗？”<BR>“不全是。scoped_ptr和scoped_array是不可以拷贝的。”<BR>“不可以拷贝？那么，如果我有一个作为类的成员-”我拿起笔说，开始在白板上涂写：</P><SPAN id=Codehighlighter1_8_34_Open_Text>
<P></SPAN></P><SPAN id=Codehighlighter1_8_34_Open_Text>
<P></SPAN></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">class</SPAN><SPAN style="COLOR: #000000">&nbsp;T<BR><IMG id=Codehighlighter1_8_31_Open_Image onclick="this.style.display='none'; Codehighlighter1_8_31_Open_Text.style.display='none'; Codehighlighter1_8_31_Closed_Image.style.display='inline'; Codehighlighter1_8_31_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_8_31_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_8_31_Closed_Text.style.display='none'; Codehighlighter1_8_31_Open_Image.style.display='inline'; Codehighlighter1_8_31_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_8_31_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_8_31_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>scoped_ptr</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">TImpl</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;p;<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>...</SPAN></DIV>
<P></SPAN>“-我如何实现拷贝和赋值呢？”<BR>“就跟使用auto_ptr是一样，”Guru回答，然后她写了：</P>
<P></P>
<P></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">T(&nbsp;</SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">&nbsp;other):p(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;TImpl(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">other.p))<BR><IMG id=Codehighlighter1_42_48_Open_Image onclick="this.style.display='none'; Codehighlighter1_42_48_Open_Text.style.display='none'; Codehighlighter1_42_48_Closed_Image.style.display='inline'; Codehighlighter1_42_48_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_42_48_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_42_48_Closed_Text.style.display='none'; Codehighlighter1_42_48_Open_Image.style.display='inline'; Codehighlighter1_42_48_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_42_48_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_42_48_Open_Text><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>T&nbsp;</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #0000ff">operator</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">(</SPAN><SPAN style="COLOR: #0000ff">const</SPAN><SPAN style="COLOR: #000000">&nbsp;T</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">&nbsp;other)<BR><IMG id=Codehighlighter1_79_146_Open_Image onclick="this.style.display='none'; Codehighlighter1_79_146_Open_Text.style.display='none'; Codehighlighter1_79_146_Closed_Image.style.display='inline'; Codehighlighter1_79_146_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_79_146_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_79_146_Closed_Text.style.display='none'; Codehighlighter1_79_146_Open_Image.style.display='inline'; Codehighlighter1_79_146_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_79_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_79_146_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;scoped_ptr</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">TImpl</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;tmp(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;TImpl(</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">other.p));<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;p.swap(tmp);<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN></DIV>
<P>“好吧，”我一边消化这种用法一边懒洋洋的说，“那么，当我在用scoped_ptr时,我必须做和用auto_ptr一样的工作，是吗？那么为什么不直接用auto_ptr？”<BR>“因为使用auto_ptr会为了自动生成的函数编译，这并不是在做坏的事情。使用scoped_ptr使它更难发生意外无意的拷贝语义，因为如果你用编译器生成的版本的话，编译器会拒绝编译这个类。 还有，scoped_ptr不能被用在一个不完整的类型上。”我有点不知所措的看向Guru。她叹了口气，“比如这样，”她边说边在白板上写：</P>
<P></P>
<P></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">class</SPAN><SPAN style="COLOR: #000000">&nbsp;Simple;<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top>Simple</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">&nbsp;CreateSimple();<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;f()<BR><IMG id=Codehighlighter1_47_145_Open_Image onclick="this.style.display='none'; Codehighlighter1_47_145_Open_Text.style.display='none'; Codehighlighter1_47_145_Closed_Image.style.display='inline'; Codehighlighter1_47_145_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_47_145_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_47_145_Closed_Text.style.display='none'; Codehighlighter1_47_145_Open_Image.style.display='inline'; Codehighlighter1_47_145_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_47_145_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_47_145_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;auto_ptr</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">Simple</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;autoS(CreateSimple());<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;scoped_ptr</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">Simple</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;scopedS(CreateSimple());<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</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></DIV>
<P>“在这个函数里，Simple是一个不完整的类型。如果析构需要代价，那么通过auto_ptr或者scoped_ptr析构就会导致未定义的行为。当你实例化一个auto_ptr时，一些编译器会警告你，但不全是这样。另一面，scoped_ptr，如果实例化一个不完整的类型，在那之前就会产生一个编译错误。”<BR>“哦，对，当然如此，”我插了进来，以表明我明白这点。“那么我们总可以使用scoped_ptr来取代auto_ptr,是不是？”<BR>“对不起，错，”她说道，很失望。“auto_ptr仍然有自己的用处。跟auto_ptr不一样，scoped_ptr没有release()成员-也就是说它不能放弃指针的所有权。正因为如此，还因为scoped_ptr不能拷贝，当scoped_ptr出了范围的时候，它所管理的指针总会被删除。这是scoped_ptr不适合于那些你真正需要传递所有权的场合，比如工厂。<BR>“使用scoped_ptr把你的意图发给其他程序员。它告诉他们：‘这个指针不应该在当前范围外被拷贝。’另一方面，auto_ptr授权可以在创建指针的范围外传播所有权，但是在所有权传播完成后，它仍然还可以控制指针。当然，这在写异常-安全(exception-safe)的代码时很重要。”<BR>“阿，好吧，我知道了，”我咕哝着，“其他你提到的智能指针呢？”<BR>“scoped_array就像一个scoped_ptr，只是它管理一个对象数组而不是一个简单对象。scoped_array提供了一些稍为不同的访问函数。它并没有*和-&gt;操作符，但是它有[]操作符。 我相信，”她总结说，“你需要的智能指针是一个scoped_array指针。”<BR>“也许吧，”我回答，“但是我想在我决定之前我还想对这些shared_*智能指针多了解一些。”<BR>“很好，我的学...徒，对不起，我失口了。”Guru羞涩的对我笑了笑。“是的，在决定之前对所有的选择都熟悉一下是一个好的工程实践（？）。”<BR>“shared_*智能指针呢，”她指了指白板上的shared_ptr和shared_array，“是很强大的工具。他们是引用计数的指针，他们能区分拥有者和观察者。比如，使用下面这个类T：”</P>
<P></P>
<P></P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;sharing()<BR><IMG id=Codehighlighter1_15_104_Open_Image onclick="this.style.display='none'; Codehighlighter1_15_104_Open_Text.style.display='none'; Codehighlighter1_15_104_Closed_Image.style.display='inline'; Codehighlighter1_15_104_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_15_104_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_15_104_Closed_Text.style.display='none'; Codehighlighter1_15_104_Open_Image.style.display='inline'; Codehighlighter1_15_104_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_15_104_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_15_104_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;shared_ptr</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;firstShared(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;T);<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;shared_ptr</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">T</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;secondShared(firstShared);<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</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></DIV>
<P>“2个shared_ptr对象都指向相同的T对象。shared_ptr的使用计数现在是2。由于shared_ptr被引用计数了，对象在最后一个shared_ptr出了作用范围-引用计数降到0-才会销毁。<BR>“shared_*指针非常有弹性，因此你可以使用他们来持有指向不完整类型的指针。”<BR>“我记得你刚说这样不好？”<BR>“如果不注意使用的话，这样确实并不好。但是只要你指定一个当持有的对象被销毁时候会调用的函数或者函数对象，shared_*指针就能用一个指向不完整类型的指针实例化出来。比如，如果我们修改了我们上面的小函数f：”</P>
<P></P>
<P></P>
<P></P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;DestroySimple(Simple</SPAN><SPAN style="COLOR: #000000">*</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;f()<BR><IMG id=Codehighlighter1_38_160_Open_Image onclick="this.style.display='none'; Codehighlighter1_38_160_Open_Text.style.display='none'; Codehighlighter1_38_160_Closed_Image.style.display='inline'; Codehighlighter1_38_160_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_38_160_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_38_160_Closed_Text.style.display='none'; Codehighlighter1_38_160_Open_Image.style.display='inline'; Codehighlighter1_38_160_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_38_160_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_38_160_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;shared_ptr</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">Simple</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;sharedSFails(CreateSimple());<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;shared_ptr</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">Simple</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;sharedSSucceeds(CreateSimple(),&nbsp;DestroySimple);<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN></DIV>
<P>“第一个shared_ptr失败了，因为Simple是一个不完整的类型。第二个成功了，因为你已经无二义的告诉shared_ptr如何销毁这个指针。<BR>“因为shared_ 指针被设计用来拷贝的，他们都很适合用在标准容器中，包括关联容器。而且，在那些需要转换的仅有的情况下，还有特殊操作符定义出来，这些操作符创建一个新的shared_* 指针。 比如，如果我们在明显的公有继承体系中有类Base 和 Derived和一个无关联的类，我们可以这样：”</P>
<P></P>
<P></P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #0000ff">void</SPAN><SPAN style="COLOR: #000000">&nbsp;g()<BR><IMG id=Codehighlighter1_9_344_Open_Image onclick="this.style.display='none'; Codehighlighter1_9_344_Open_Text.style.display='none'; Codehighlighter1_9_344_Closed_Image.style.display='inline'; Codehighlighter1_9_344_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_9_344_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_9_344_Closed_Text.style.display='none'; Codehighlighter1_9_344_Open_Image.style.display='inline'; Codehighlighter1_9_344_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_9_344_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_9_344_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;shared_ptr</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">Base</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;sharedBase(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Derived);<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;shared_ptr</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">Derived</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;sharedDer&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;shared_dynamic_cast</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">Derived</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">(sharedBase);<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;shared_ptr</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">Unrelated</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;sharedDer&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;shared_dynamic_cast</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">Unrelated</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">(sharedBase);<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">try</SPAN><SPAN style="COLOR: #000000"><BR><IMG id=Codehighlighter1_219_305_Open_Image onclick="this.style.display='none'; Codehighlighter1_219_305_Open_Text.style.display='none'; Codehighlighter1_219_305_Closed_Image.style.display='inline'; Codehighlighter1_219_305_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_219_305_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_219_305_Closed_Text.style.display='none'; Codehighlighter1_219_305_Open_Image.style.display='inline'; Codehighlighter1_219_305_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN id=Codehighlighter1_219_305_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_219_305_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shared_ptr</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">Unrelated</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;oops&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;shared_polymorphic_cast</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">Unrelated</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000">(sharedBase);<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/InBlock.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">catch</SPAN><SPAN style="COLOR: #000000">(bad_cast)<BR><IMG id=Codehighlighter1_327_342_Open_Image onclick="this.style.display='none'; Codehighlighter1_327_342_Open_Text.style.display='none'; Codehighlighter1_327_342_Closed_Image.style.display='inline'; Codehighlighter1_327_342_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_327_342_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_327_342_Closed_Text.style.display='none'; Codehighlighter1_327_342_Open_Image.style.display='inline'; Codehighlighter1_327_342_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN id=Codehighlighter1_327_342_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_327_342_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//...</SPAN><SPAN style="COLOR: #008000"><BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN></DIV>
<P>“还有一个shared_static_cast，是用在需要的极少的场合的，”Guru总结道。<BR>我研究了这个函数一会。“好吧，我看看我是否能遵循这些。第一个shared_dynamic_cast执行针对智能指针的dynamic_cast并且返回一个新的智能指针。如果dynamic_cast失败了，引用计数将会怎样？”<BR>Guru赞许的点点头。“那样的话，原始的计数将不受影响，新的shared_ptr将包含一个NULL指针。你也许能从try/catch子句推出来，shared_polymorphic_cast也会尝试对拥有的指针执行dynamic_cast。如果转换失败，就会抛出一个bad_cast异常。”<BR>“喔，”我暗暗叫绝，“这才是那个类。看起来真是为此而设计的。”<BR>“确实，”Guru也同意。“但是还有2件事要注意。引用计数很简单，但不能检测循环引用。还有，shared_ptr不能实现写方式的拷贝形式，因此如果要实现Pimpl，你必须多加小心。”<BR>我对它捉摸了半天，发现我很喜欢它。“嘿，”我想起来什么，又说，“那么你提到的weak_ptr呢？”<BR>“阿，是的。weak_ptr用于关联shared_ptr。weak_ptr是一个观察者，它并不影响共享对象的使用计数。weak_ptr的主要目的是用来允许shared_ptr参与到循环依赖中来-A持有B的引用，B同时也持有A的引用。我更喜欢把weak_ptr当作一个俱乐部中的关联成员-它没有投票权，但是可以参加俱乐部活动。”<BR>“呒...”我想了一会。“因为weak_ptr没有影响使用计数，当weak_ptr在用一个共享对象，此时如果俱乐部解散-换句话说，最后一个shared_ptr出了范围-会发生什么事呢？”<BR>“那样的话，weak_ptr管理的指针会被设置为NULL。讲到NULL，没有可以卸领（dereferencing）的操作符，比如*，-〉，[]，会在卸领之前检查一个NULL指针。因此，正如你所指出的在卸领之前原始指针非空，你还必须检查一个智能指针不为空。这个限制也适用于Boost库中所有的智能指针。”<BR>“老大，有太多的材料要记了，”我说着，看着我自己潦草的白板。<BR>“别担心，”Guru笑道，准备站起来走了。“我会发email给你Boost精简库的网址和一个小程序，它可以用来练习和示例各种指针。”当然，她对自己的话从不食言，几分钟后我收到了她的email。我揉了揉我的眼睛，因为我只看到：<BR>“我的小学徒，这儿是那个Boost文章的地址：&lt;<A href="http://www.boost.org/libs/smart_ptr/smart_ptr.htm">www.boost.org/libs/smart_ptr/smart_ptr.htm</A>&gt;。看看它，再思考一下附件中关于谦虚的寓言。”</P><img src ="http://www.cppblog.com/llface/aggbug/1366.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/llface/" target="_blank">西山居士</a> 2005-11-28 16:32 <a href="http://www.cppblog.com/llface/articles/1366.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>