<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet href='http://feed.siwei.org/styles/feedsky8.xsl' type='text/xsl' ?><!--这是一个由Feedsy提供技术支持的Feed，为了提高读者阅读的体验，以及满足用户美化自己Feed的需要，我们设计了多种精美的Feed模板，提供给大家选择，所有最终呈现出来的样式，皆由用户自愿选择使用，未经许可，任何团体和个人，请不要擅自修改样式或者盗用，这是对于用户选择权的尊重。--><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:fs="http://www.feedsky.com/namespace/feed" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link href="http://feed.siwei.org" type="application/rss+xml" rel="self"></atom:link><fs:self_link href="http://feed.feedsky.com/siwei" type="application/rss+xml"></fs:self_link><lastBuildDate>Thu, 19 Jan 2012 02:51:40 GMT</lastBuildDate><title>思维 of 司维</title><description>.Net + JS + Python</description><image><url>http://www.feedsky.com/images/feedsky_logologo.gif</url><title>思维 of 司维</title><link>http://wei.si/blog</link></image><link>http://wei.si/blog</link><sy:updatePeriod>hourly</sy:updatePeriod><sy:updateFrequency>1</sy:updateFrequency><language>en</language><pubDate>Thu, 19 Jan 2012 02:51:40 GMT</pubDate><item><title>微软的Playful Programming？？</title><link>http://wei.si/blog/2012/01/playful-programming-from-microsoft/</link><content:encoded>&lt;p&gt;这几天在刷PSV奖杯，结果看到这么个东西：&lt;a href=&quot;http://channel9.msdn.com/achievements/visualstudio&quot; target=&quot;_blank&quot;&gt;微软的Visual Studio Achievements扩展&lt;/a&gt;。&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img class=&quot;aligncenter&quot; src=&quot;http://channel9.msdn.com/styles/images/achievements/VSscreenshot1.png&quot; alt=&quot;&quot; width=&quot;368&quot; height=&quot;221&quot; /&gt;&lt;/p&gt;
&lt;p&gt;作用就是在程序员完成一些“成就”后给予提示和记录，获取相应的称号。例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在一个类里面声明100个成员变量（Field Master）&lt;/li&gt;
&lt;li&gt;一行代码写300个字符（Scroll Bar Wizard）&lt;/li&gt;
&lt;li&gt;使用“Close All But This”10次（Obsessive Compulsive Disorder）&lt;/li&gt;
&lt;li&gt;……&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;看来以后可以加班刷成就啦！&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/597955191/siwei/feedsky/s.gif?r=http://wei.si/blog/2012/01/playful-programming-from-microsoft/&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</content:encoded><wfw:commentRss>http://wei.si/blog/2012/01/playful-programming-from-microsoft/feed/</wfw:commentRss><slash:comments>0</slash:comments><description>这几天在刷PSV奖杯，结果看到这么个东西：微软的Visual Studio Achievements扩展。

作用就是在程序员完成一些“成就”后给予提示和记录，获取相应的称号。例如：

在一个类里面声明100个成员变量（Field Master）
一行代码写300个字符（Scroll Bar Wizard）
使用“Close All But This”10次（Obsessive Compulsive Disorder）
……

看来以后可以加班刷成就啦！&lt;img src=&quot;http://www1.feedsky.com/t1/597955191/siwei/feedsky/s.gif?r=http://wei.si/blog/2012/01/playful-programming-from-microsoft/&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</description><category>程序</category><pubDate>Thu, 19 Jan 2012 10:51:40 +0800</pubDate><author>Si Wei</author><comments>http://wei.si/blog/2012/01/playful-programming-from-microsoft/#comments</comments><guid isPermaLink="false">http://wei.si/blog/?p=643578</guid><dc:creator>Si Wei</dc:creator><fs:srclink>http://wei.si/blog/2012/01/playful-programming-from-microsoft/</fs:srclink><fs:srcfeed>http://wei.si/blog/feed/</fs:srcfeed><fs:itemid>feedsky/siwei/~8249691/597955191/1229498</fs:itemid></item><item><title>Objective-C学习笔记（1-3）</title><link>http://wei.si/blog/2012/01/objective-c-study-notes-1-3/</link><content:encoded>&lt;p&gt;去年因为项目需要临时学了一段时间Objective-C，可惜直到现在都适应不了这门语言。学习过程中根据不同主题记了一些东西下来，发出来共享，但愿能帮到一些同为入门菜鸟的Objective-C学习者，不过笔记中肯定有错，这个我比较有自知之明。笔记中的所有时间表达（昨天、这段时间）都不以现在为准，因为是好几个月之前写下的。&lt;/p&gt;
&lt;h2&gt;目录&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;#chap01&quot;&gt;构造和拷贝构造&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#chap02&quot;&gt;动态特性和RTTI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#chap03&quot;&gt;内存管理和标准C区别&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;chap01&quot;&gt;01构造和拷贝构造&lt;/h2&gt;
&lt;h3&gt;首先是有关构造函数&lt;/h3&gt;
&lt;p&gt;我想实现子类基类不同数量参数的构造方式，结果昨天试验了几种方法都不行。&lt;/p&gt;
&lt;p&gt;参见下面的代码，Person是基类，实现了一个两参数的构造函数initWithArgs。子类Coder重载了这个方法，多了一个参数，试图重用基类的方法：&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;// person的构造函数&lt;/span&gt;
&lt;span style=&quot;color: #002200;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; initWithArgs &lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #400080;&quot;&gt;NSString&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; aName andAge&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; aAge &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#123;&lt;/span&gt;
Person&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt; person &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;Person alloc&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; init&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;person setName&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt; aName&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;person setAge&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt; aAge&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
&lt;span style=&quot;color: #a61390;&quot;&gt;return&lt;/span&gt; person;
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#125;&lt;/span&gt;
&lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;// coder的构造函数&lt;/span&gt;
&lt;span style=&quot;color: #002200;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; initWithArgs &lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #400080;&quot;&gt;NSString&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; aName andAge&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;NSInteger&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; aAge andLanguage&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #400080;&quot;&gt;NSString&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;aLanguage &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#123;&lt;/span&gt;
&lt;span style=&quot;color: #a61390;&quot;&gt;return&lt;/span&gt; ???  &lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;//这里要返回什么&lt;/span&gt;
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;结果昨天尝试了N种方法，全都不行！&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;// 不行, crash!&lt;/span&gt;
&lt;span style=&quot;color: #a61390;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt; self &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;super initWithArgs&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;aName andAge&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;aAge&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#123;&lt;/span&gt;
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;self setLanguage&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;aLanguage&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#125;&lt;/span&gt;
&lt;span style=&quot;color: #a61390;&quot;&gt;return&lt;/span&gt; self;
&amp;nbsp;
&lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;// 不行，没有crash，但是基类的参数name和age都设置失败&lt;/span&gt;
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;super initWithArgs&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;aName andAge&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;aAge&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;self setLanguage&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;aLanguage&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
&lt;span style=&quot;color: #a61390;&quot;&gt;return&lt;/span&gt; self;
&amp;nbsp;
&lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;// 好用，但我们的基类构造函数不就没用了吗&lt;/span&gt;
Coder&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt; coder &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;Coder alloc&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; init&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;coder setName&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;aName&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;coder setAge&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;aAge&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;coder setLanguage&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;aLanguage&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
&lt;span style=&quot;color: #a61390;&quot;&gt;return&lt;/span&gt; coder;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;问题在于基类的构造定义，要用[self class]获取到当前self指针的类型才对&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;Person&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt; person &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;self class&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; alloc&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; init&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;子类的构造函数：&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;Coder&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt; coder &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;super initWithArgs&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;aName andAge&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;aAge&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;coder setLanguage&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;aLanguage&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
&lt;span style=&quot;color: #a61390;&quot;&gt;return&lt;/span&gt; coder;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;或者用更单纯一点的调用：&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;self initWithArgs&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;aName andAge&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;aAge&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
    &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;self setLanguage&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;aLanguage&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
    &lt;span style=&quot;color: #a61390;&quot;&gt;return&lt;/span&gt; self;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;span id=&quot;more-643570&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;简洁构造函数&lt;/h3&gt;
&lt;p&gt;类似[类名]With[参数名]这样的构造函数，也是类方法，好处在于使用者不用alloc/release操作。内部通过autorelease实现&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #002200;&quot;&gt;+&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; personWithName&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #400080;&quot;&gt;NSString&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;aName andAge&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;NSInteger&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;aAge &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#123;&lt;/span&gt;
&lt;span style=&quot;color: #a61390;&quot;&gt;id&lt;/span&gt; ret &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;self class&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; alloc&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; initWithArgs&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;aName andAge&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;aAge&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
&lt;span style=&quot;color: #a61390;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;ret autorelease&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;注意到没，构造方式很像有参数构造函数，也需要用[self class]指定类型。不然子类调用的时候就会出问题。&lt;/p&gt;
&lt;p&gt;使用一下：&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;Person&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt; siwei &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;Person personWithName&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;&amp;quot;Si Wei&amp;quot;&lt;/span&gt; andAge&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #2400d9;&quot;&gt;25&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
NSLog&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #bf1d1a;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;&amp;quot;%@&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;siwei GetInfo&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #2400d9;&quot;&gt;0&lt;/span&gt; TheSecondArg&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;NO&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;;
Coder&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt; coder &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;Coder personWithName&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;&amp;quot;Si Wei&amp;quot;&lt;/span&gt; andAge&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #2400d9;&quot;&gt;25&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
NSLog&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #bf1d1a;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;&amp;quot;%@&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;coder GetInfo&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #2400d9;&quot;&gt;0&lt;/span&gt; TheSecondArg&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;NO&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3&gt;拷贝构造&lt;/h3&gt;
&lt;h4&gt;allocWithZone&lt;/h4&gt;
&lt;p&gt;通过copy函数实现，它会调用copyWithZone，所以在NSObject为基类的类中实现这个协议即可。注意那个allocWithZone方法和刚才已经出现过两次的[self class]：&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;// Person 类&lt;/span&gt;
&lt;span style=&quot;color: #002200;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; copyWithZone &lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;NSZone&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;zone &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#123;&lt;/span&gt;
    Person&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt; clone &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;self class&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; allocWithZone&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;zone&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
    &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;clone setName&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;self name&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
    &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;clone setAge&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;self age&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;; &lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;// 或者写成 clone-&amp;amp;gt;age = self-&amp;amp;gt;age;&lt;/span&gt;
    &lt;span style=&quot;color: #a61390;&quot;&gt;return&lt;/span&gt; clone;
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;对于子类来说，如果父类实现了这个方法（就像上面的Person::copyWithZone），可以直接调用，省去继承而来的数据成员的拷贝操作：&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;// Coder 类&lt;/span&gt;
&lt;span style=&quot;color: #002200;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; copyWithZone &lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;NSZone&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;zone &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#123;&lt;/span&gt;
    Coder&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt; clone &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;super copyWithZone&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;zone&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
    &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;clone setLanguage&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;self language&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
    &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;clone setComputer&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;self computer&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;; &lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;// shallow copy。也可以写成clone-&amp;amp;gt;computer = [[self computer] retain]];&lt;/span&gt;
    &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;clone setLeader&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;self leader&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; copyWithZone&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;zone&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;  &lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;// deep copy&lt;/span&gt;
    &lt;span style=&quot;color: #a61390;&quot;&gt;return&lt;/span&gt; clone;
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;值得注意的是，在上面这段代码中，用了几种不同的copy方式&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[clone setProperty:[self property]]; 值拷贝，适用于各种值类型以及NSString*&lt;/li&gt;
&lt;li&gt;clone-&amp;gt;computer = [[self computer] retain]]; 相当于浅拷贝，只引用一下&lt;/li&gt;
&lt;li&gt;[clone setProperty:[[self property] copyWithZone:zone]]; 深拷贝，但前提是这个属性的类必须实现copy重载才行。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以下面代码的执行结果就一目了然了：coder1的leader重新setAge后，coder2的leader属性没有改变，age还是150。&lt;/p&gt;
&lt;p&gt;如果在b)里面使用[clone leader:[self leader]];的话，coder2的leader属性也会随之改变。&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;Coder&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt; coder1 &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;Coder personWithName&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;&amp;quot;Si Wei&amp;quot;&lt;/span&gt; andAge&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #2400d9;&quot;&gt;25&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
    &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;coder1 setLanguage&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;&amp;quot;C#&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
&amp;nbsp;
    Person&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt; leader &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;Person alloc&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; initWithArgs&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;&amp;quot;Leader&amp;quot;&lt;/span&gt; andAge&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #2400d9;&quot;&gt;150&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
    &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;coder1 setLeader&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;leader&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
    Computer&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt; computer &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;Computer alloc&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; init&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
    &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;coder1 setComputer&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;computer&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
&amp;nbsp;
    Coder&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt; coder2 &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;coder1 copy&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
    NSLog&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #bf1d1a;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;&amp;quot;%@&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;coder2 leader&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; GetInfo&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #2400d9;&quot;&gt;0&lt;/span&gt; TheSecondArg&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;NO&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;; &lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;// Leader, 150&lt;/span&gt;
&amp;nbsp;
    &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;coder1 leader&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; setAge&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #2400d9;&quot;&gt;99&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
    NSLog&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #bf1d1a;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;&amp;quot;%@&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;coder2 leader&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; GetInfo&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #2400d9;&quot;&gt;0&lt;/span&gt; TheSecondArg&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;NO&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;; &lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;// Leader, 150&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;除了allocWithZone之外，还可以使用NSCopyObject()实现拷贝&lt;/p&gt;
&lt;h3&gt;NSCopyObject&lt;/h3&gt;
&lt;p&gt;这是二进制拷贝，也就是说对于值类型可以省去赋值的过程（当然也包括NSString*这个指针中的异类）&lt;/p&gt;
&lt;p&gt;指针则需要自己进行操作，或者retain、或者赋值。假设基类多了一个指针成员：&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #002200;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; copyWithZone &lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;NSZone&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;zone &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;//Person* clone = [[self class] allocWithZone:zone];&lt;/span&gt;
    Person&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt; clone &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; NSCopyObject&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt; self, &lt;span style=&quot;color: #2400d9;&quot;&gt;0&lt;/span&gt;, zone &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;;
    &lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;//[clone setName:[self name]];  // 不再需要&lt;/span&gt;
    &lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;//[clone setAge:[self age]];  // 不再需要&lt;/span&gt;
    clone&lt;span style=&quot;color: #002200;&quot;&gt;-&amp;amp;&lt;/span&gt;gt;pObject &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #a61390;&quot;&gt;nil&lt;/span&gt;;  &lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;// 需要，重置指针&lt;/span&gt;
    &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;clone setPObject&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;self&lt;span style=&quot;color: #002200;&quot;&gt;-&amp;amp;&lt;/span&gt;gt;pObject&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
    &lt;span style=&quot;color: #a61390;&quot;&gt;return&lt;/span&gt; clone;
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;于子类来说，一定要知道父类的copyWithZone实现才能决定用什么方式copy：&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #002200;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; copyWithZone &lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;NSZone&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;zone &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#123;&lt;/span&gt;
&lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;//[clone setLanguage:[self language]]; // 不再需要，父类实现了NSCopyObject()&lt;/span&gt;
    Coder&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt; clone &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;super copyWithZone&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;zone&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
    &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;clone&lt;span style=&quot;color: #002200;&quot;&gt;-&amp;amp;&lt;/span&gt;gt;computer retain&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;; &lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;// 父类实现了NSCopyObject()，虽然指针是拷贝过来了，但需要增加引用计数&lt;/span&gt;
    &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;clone setLeader&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;self leader&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; copyWithZone&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;zone&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;  &lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;// 需要也进行copy的对象必须要调用copy，不管是不是NSCopyObject()&lt;/span&gt;
    &lt;span style=&quot;color: #a61390;&quot;&gt;return&lt;/span&gt; clone;
       &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3&gt;dummy cloning和mutable copying&lt;/h3&gt;
&lt;p&gt;简单来说就是返回一个自身引用&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #002200;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; copyWithZone&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;NSZone&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;zone
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;// 返回自身，增加一个引用&lt;/span&gt;
    &lt;span style=&quot;color: #a61390;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;self retain&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;作用？对于Mutable对象来说可以实现对于非Mutable对象的dummy clong后增加实现可变特性的方法。例如NSMutableString对于NSString&lt;/p&gt;
&lt;p&gt;除了刚才的NSCopy外，还有一个NSMutableCopying协议，需要实现一个方法，它返回可变对象。操作方法是[object mutableCopy]。它的用处就是可以让Mutable Object的copy也是Mutable的，例如NSMutableArray如果用copy的话，返回的对象是不能修改的，这个时候需要用mutableCopy。具体的实现方法和copyWithZone没什么区别。&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #002200;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; mutableCopyWithZone&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;NSZone&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;zone;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;chap02&quot;&gt;02动态特性和RTTI&lt;/h2&gt;
&lt;h3&gt;KVC（Key-Value Coding）&lt;/h3&gt;
&lt;p&gt;可以通过字符串访问类成员。有点像字典。&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;NSLog&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #bf1d1a;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;&amp;quot;%@&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;coder1 valueForKey&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;&amp;quot;leader&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; GetInfo&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #2400d9;&quot;&gt;0&lt;/span&gt; TheSecondArg&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;NO&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;;
    &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;coder1 setValue&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;&amp;quot;New Si Wei&amp;quot;&lt;/span&gt; forKey&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
    NSLog&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #bf1d1a;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;&amp;quot;%@&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;coder1 GetInfo&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #2400d9;&quot;&gt;0&lt;/span&gt; TheSecondArg&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;NO&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;对于成员的成员，需要用valueForKeyPath。当然对于自己的成员也可以用。&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;NSLog&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #bf1d1a;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;&amp;quot;%@&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;coder1 valueForKeyPath&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;&amp;quot;leader.name&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;调用的顺序大概是&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;valueForKey:@”foo”
&lt;ol&gt;
&lt;li&gt;getFoo方法、foo方法、isFoo方法&lt;/li&gt;
&lt;li&gt;如果类accessInstanceVariablesDirectly返回YES那么是依次是_foo、_isFoo、foo和isFoo&lt;/li&gt;
&lt;li&gt;还没找到就调用类的valueForUndefinedKey，默认行为是抛出异常NSUnknownKeyException&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;setValue:forKey:@”foo”
&lt;ol&gt;
&lt;li&gt;setFoo方法&lt;/li&gt;
&lt;li&gt;如果类accessInstanceVariablesDirectly返回YES那么是依次是_foo、_isFoo、foo和isFoo&lt;/li&gt;
&lt;li&gt;还没找到就调用类的setValue:forUndefinedKey，默认行为是抛出异常NSUnknownKeyException&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;introspection&lt;/h3&gt;
&lt;p&gt;OOP语言必备的特性，简单说就是在运行时检查类的类型&lt;/p&gt;
&lt;p&gt;从下面代码可以看出来，isKindOfClass检查对象是否是某类以及其子类的实例；isMemberOfClass只检查是否是某类的实例。&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;Class&lt;/span&gt; personClass &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;Person class&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
    &lt;span style=&quot;color: #a61390;&quot;&gt;Class&lt;/span&gt; coderClass &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;Coder class&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
    NSLog&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #bf1d1a;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;&amp;quot;%d, %d, %d, %d, %d, %d, %d, %d&amp;quot;&lt;/span&gt;,
        &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;leader isMemberOfClass&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;personClass&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;, &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;leader isKindOfClass&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;personClass&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;, &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;leader isMemberOfClass&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;coderClass&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;, &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;leader isKindOfClass&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;coderClass&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;,
        &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;coder1 isMemberOfClass&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;personClass&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;, &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;coder1 isKindOfClass&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;personClass&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;, &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;coder1 isMemberOfClass&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;coderClass&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;, &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;coder1 isKindOfClass&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;coderClass&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;;
&lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;//  YES, YES, NO, NO, NO, YES, YES, YES&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3&gt;实际编程中的一些动态特性类&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;SEL：selector相当于指向成员函数的指针，需要指定target才可以调用。通过selector生成的method signature可以用来初始化NSInvocation。
&lt;ul&gt;
&lt;li&gt;直接从方法名取得selector用@selector()或者NSSelectorFromString，逆操作NSStringFromSelector&lt;/li&gt;
&lt;li&gt;对于实例用performSelector调用具体的方法&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Class：类的元数据，通过[instance class]、[instance className]或者NSClassFromString拿到，也有一个逆操作NSStringFromClass&lt;/li&gt;
&lt;li&gt;IMP：其实就是一个函数指针，返回id，参数为id, selector, …，写着比自定义的方便而已，见下面的例子：&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;Person&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt; me &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;Person alloc&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; initWithArgs&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;&amp;quot;SW&amp;quot;&lt;/span&gt; TheAge&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #2400d9;&quot;&gt;25&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
&lt;span style=&quot;color: #a61390;&quot;&gt;SEL&lt;/span&gt; selector &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #a61390;&quot;&gt;@selector&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;GetInfo&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;TheSecondArg&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;;
&lt;span style=&quot;color: #400080;&quot;&gt;NSString&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt;pFunc &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #a61390;&quot;&gt;id&lt;/span&gt;, &lt;span style=&quot;color: #a61390;&quot;&gt;SEL&lt;/span&gt;, &lt;span style=&quot;color: #a61390;&quot;&gt;int&lt;/span&gt;, &lt;span style=&quot;color: #a61390;&quot;&gt;BOOL&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;;
pFunc &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #400080;&quot;&gt;NSString&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;id&lt;/span&gt;, &lt;span style=&quot;color: #a61390;&quot;&gt;SEL&lt;/span&gt;, &lt;span style=&quot;color: #a61390;&quot;&gt;int&lt;/span&gt;, &lt;span style=&quot;color: #a61390;&quot;&gt;BOOL&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;me methodForSelector&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;selector&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
&lt;span style=&quot;color: #a61390;&quot;&gt;IMP&lt;/span&gt; imp &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;me methodForSelector&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;selector&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
NSLog&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #bf1d1a;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;&amp;quot;%@&amp;quot;&lt;/span&gt;, pFunc&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt; me, selector, &lt;span style=&quot;color: #2400d9;&quot;&gt;100&lt;/span&gt;, &lt;span style=&quot;color: #a61390;&quot;&gt;YES&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;;
NSLog&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #bf1d1a;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #bf1d1a;&quot;&gt;&amp;quot;%@&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #400080;&quot;&gt;NSString&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;imp&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt; me, selector, &lt;span style=&quot;color: #2400d9;&quot;&gt;100&lt;/span&gt;, &lt;span style=&quot;color: #a61390;&quot;&gt;YES&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Invocation Forward：proxy类的工作，需要重载三个函数&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;BOOL&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;respondsToSelector&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;SEL&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;aSelector：判断selector是否属于自己的某个成员
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #400080;&quot;&gt;NSMethodSignature&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;methodSignatureForSelector&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;SEL&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;aSelector：通过selector拿到method signature
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;forwardInvocation&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #400080;&quot;&gt;NSInvocation&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;invocation：转发Invocation到相应的成员上
&lt;span style=&quot;color: #002200;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #400080;&quot;&gt;NSMethodSignature&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; methodSignatureForSelector&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;SEL&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt;selector &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span style=&quot;color: #400080;&quot;&gt;NSMethodSignature&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt; methodSig &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;fwdTarget methodSignatureForSelector&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;selector&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
    &lt;span style=&quot;color: #a61390;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt; methodSig &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#123;&lt;/span&gt;
        &lt;span style=&quot;color: #a61390;&quot;&gt;return&lt;/span&gt; methodSig;
    &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#125;&lt;/span&gt;
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#125;&lt;/span&gt;
&lt;span style=&quot;color: #002200;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; forwardInvocation&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #400080;&quot;&gt;NSInvocation&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; invocation &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;invocation invokeWithTarget&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;self fwdTarget&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;chap03&quot;&gt;03内存管理和标准C区别&lt;/h2&gt;
&lt;h3&gt;数据成员访问器&lt;/h3&gt;
&lt;p&gt;数据成员的setter设定。不管哪个教程，都告诉我们setter是不能这么写的：&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #002200;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #a61390;&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; setLanguage &lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #400080;&quot;&gt;NSString&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; aLanguage &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;self language&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt; aLanguage&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;  &lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;// 糟糕代码！外部如果释放了aLanguage指向的对象，内部使用就会出错&lt;/span&gt;
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;也不能这么写&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;language &lt;span style=&quot;color: #002200;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;aLanguage retain&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;  &lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;// 糟糕代码！内部成员原先指向的对象没法释放了！&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;当然这样也不行&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;language release&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
       &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;self setLanguage&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;aLanguage&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;; &lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;// 糟糕代码！如果language == aLanguage的话就多release了一次。&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;所以我们被告知应该这么写&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;language autorelease&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
       &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;self setLanguage&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;aLanguage&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;; &lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;// Good&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;其实从第三个例子考虑，也可以写成&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;aLanguage retain&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
       &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;language release&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
       &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;self setLanguage&lt;span style=&quot;color: #002200;&quot;&gt;:&lt;/span&gt;aLanguage&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;数据成员的getter设定。有的时候对于开放给外界的数据成员不希望进行修改，又不想用const关键字的话，可以考虑返回一个copy&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;objc&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #002200;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#40;&lt;/span&gt;Person&lt;span style=&quot;color: #002200;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#41;&lt;/span&gt; leader &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span style=&quot;color: #a61390;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#91;&lt;/span&gt;leader copy&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt; autorelease&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#93;&lt;/span&gt;;
    &lt;span style=&quot;color: #11740a; font-style: italic;&quot;&gt;//return leader;&lt;/span&gt;
&lt;span style=&quot;color: #002200;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;当然能这么做的前提是Person类实现了copyWithZone&lt;/p&gt;
&lt;h3&gt;release和垃圾收集器&lt;/h3&gt;
&lt;p&gt;什么情况才需要autorelease？显式地调用了alloc、使用了copy（mutableCopy）以及retain之后。&lt;/p&gt;
&lt;p&gt;垃圾收集器实现了一个灵活的GC，省得我们自己去retain, release和autorelease。开启了GC之后这三个函数都没用了。不过iPhone开发环境中似乎不能用GC？&lt;/p&gt;
&lt;p&gt;__weak和__strong声明。什么时候需要弱引用？集合类，因为如果集合对其中的元素都拥有强引用的话，那么这些引用的实际对象就没法析构了（在集合类被咔嚓之前永远有一个ref count）。而弱引用在对象消失后自动变为nil。&lt;/p&gt;
&lt;p&gt;autorelease不能滥用，因为它实际上是lazy deallocation，一般来说thread不结束都没法回收。&lt;/p&gt;
&lt;p&gt;对于对象引用的维护，永远是使用者责任更大。因为开发者不知道自己的对象可能被引用多少次。&lt;/p&gt;
&lt;h3&gt;这些东西不能用&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;模板&lt;/li&gt;
&lt;li&gt;默认参数&lt;/li&gt;
&lt;li&gt;Friend&lt;/li&gt;
&lt;li&gt;inline（但其实Obj-C兼容C99，也可以使用inline关键字）&lt;/li&gt;
&lt;li&gt;initialization list&lt;/li&gt;
&lt;li&gt;方法的const修饰&lt;/li&gt;
&lt;/ul&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/597572838/siwei/feedsky/s.gif?r=http://wei.si/blog/2012/01/objective-c-study-notes-1-3/&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</content:encoded><wfw:commentRss>http://wei.si/blog/2012/01/objective-c-study-notes-1-3/feed/</wfw:commentRss><slash:comments>0</slash:comments><description>去年因为项目需要临时学了一段时间Objective-C，可惜直到现在都适应不了这门语言。学习过程中根据不同主题记了一些东西下来，发出来共享，但愿能帮到一些同为入门菜鸟的Objective-C学习者，不过笔记中肯定有错，这个我比较有自知之明。笔记中的所有时间表达（昨天、这段时间）都不以现在为准，因为是好几个月之前写下的。
目录

构造和拷贝构造
动态特性和RTTI
内存管理和标准C区别

01构造和拷贝构造
首先是有关构造函数
我想实现子类基类不同数量参数的构造方式，结果昨天试验了几种方法都不行。
参见下面的代码，Person是基类，实现了一个两参数的构造函数initWithArgs。子类Coder重载了这个方法，多了一个参数，试图重用基类的方法：

// person的构造函数
- &amp;#40;id&amp;#41; initWithArgs : &amp;#40;NSString*&amp;#41; aName andAge:&amp;#40;int&amp;#41; aAge &amp;#123;
Person* person = &amp;#91;&amp;#91;Person alloc&amp;#93; init&amp;#93;;
&amp;#91;person setName: aName&amp;#93;;
&amp;#91;person setAge: aAge&amp;#93;;
return person;
&amp;#125;
// coder的构造函数
- &amp;#40;id&amp;#41; initWithArgs : &amp;#40;NSString*&amp;#41; aName andAge:&amp;#40;NSInteger&amp;#41; aAge andLanguage:&amp;#40;NSString*&amp;#41;aLanguage &amp;#123;
return ???  //这里要返回什么
&amp;#125;

结果昨天尝试了N种方法，全都不行！

// 不行, crash!
if &amp;#40; self = &amp;#91;super initWithArgs:aName andAge:aAge&amp;#93; &amp;#41; &amp;#123;
&amp;#91;self setLanguage:aLanguage&amp;#93;;
&amp;#125;
return self;
&amp;#160;
// 不行，没有crash，但是基类的参数name和age都设置失败
&amp;#91;super initWithArgs:aName andAge:aAge&amp;#93;;
&amp;#91;self setLanguage:aLanguage&amp;#93;;
return self;
&amp;#160;
// 好用，但我们的基类构造函数不就没用了吗
Coder* coder = &amp;#91;&amp;#91;Coder alloc&amp;#93; [...]&lt;img src=&quot;http://www1.feedsky.com/t1/597572838/siwei/feedsky/s.gif?r=http://wei.si/blog/2012/01/objective-c-study-notes-1-3/&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</description><category>程序</category><pubDate>Tue, 17 Jan 2012 16:49:17 +0800</pubDate><author>Si Wei</author><comments>http://wei.si/blog/2012/01/objective-c-study-notes-1-3/#comments</comments><guid isPermaLink="false">http://wei.si/blog/?p=643570</guid><dc:creator>Si Wei</dc:creator><fs:srclink>http://wei.si/blog/2012/01/objective-c-study-notes-1-3/</fs:srclink><fs:srcfeed>http://wei.si/blog/feed/</fs:srcfeed><fs:itemid>feedsky/siwei/~8249691/597572838/1229498</fs:itemid></item><item><title>阅读总结2011</title><link>http://wei.si/blog/2011/12/reading-summary-2011/</link><content:encoded>&lt;p&gt;终于到了2011最后一天，可以发各种总结了。阅读还是用&lt;a href=&quot;http://imnerd.org/douban/&quot; target=&quot;_blank&quot;&gt;http://imnerd.org/douban/&lt;/a&gt;进行统计。&lt;/p&gt;
&lt;h2&gt;题外话：动画和游戏&lt;/h2&gt;
&lt;p&gt;至于动画、游戏什么的，自然用&lt;a href=&quot;http://bgm.tv/award/2011&quot; target=&quot;_blank&quot;&gt;Bangumi的年鉴功能&lt;/a&gt;。懒得单发，记录在此了：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;「Bangumi 2011 年鉴」 2011 年，我看了 28 部动画，读了 本书，听了 1 张音乐，玩了 7 部游戏，看了 1 部剧集，参与了 73 次讨论，进行了 0 次条目编辑。&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;在这28部动画中印象最深刻的是还在放送的&lt;a href=&quot;http://wei.si/blog/2011/11/chihayafuru/&quot; target=&quot;_blank&quot;&gt;《ちはやふる》（歌牌情缘）&lt;/a&gt;，游戏里面觉得最好的是一款老游戏&lt;a href=&quot;http://wei.si/blog/2011/09/jyuusei-to-diamond-played/&quot; target=&quot;_blank&quot;&gt;《枪声与钻石》&lt;/a&gt;。当然今年玩游戏太少了，而且基本都是PSP上的AVG，最近这三个月已经写了大概四篇相关的玩后体会。&lt;/p&gt;
&lt;h2&gt;数据&lt;/h2&gt;
&lt;p&gt;回到正题，2011年的阅读数量为112，较之前年回落较多。原因不外乎是工作太忙，另外则是去掉了漫画，轻小说也只保留第一卷，确保统计水分不太大。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://wei.si/blog/wp-content/uploads/2011/12/read_2011.png&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-643565&quot; title=&quot;read_2011&quot; src=&quot;http://wei.si/blog/index.php?feedimage=wp-content/uploads/2011/12/read_2011-300x150.png&quot; alt=&quot;&quot; width=&quot;300&quot; height=&quot;150&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;尽管如此，其实这112本书中有80%还是推理小说/轻小说，专业书以及学习类书籍大概只有10本……？所以推荐列表还是从推理小说开始吧（书籍链接在图片上）。&lt;/p&gt;
&lt;h2&gt;推荐的推理小说/轻小说类作品&lt;/h2&gt;
&lt;p&gt;&lt;a style=&quot;float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;&quot; title=&quot;我的日常推理&quot; href=&quot;http://book.douban.com/subject/6006584/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://img3.douban.com/spic/s4657354.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; /&gt;&lt;/a&gt; &lt;a style=&quot;float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;&quot; title=&quot;恋爱曲线&quot; href=&quot;http://book.douban.com/subject/5349518/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://img3.douban.com/spic/s4525343.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; /&gt;&lt;/a&gt; &lt;a style=&quot;float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;&quot; title=&quot;空之境界（上下集合售）&quot; href=&quot;http://book.douban.com/subject/1349295/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://img3.douban.com/spic/s3018266.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; /&gt;&lt;/a&gt; &lt;a style=&quot;float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;&quot; title=&quot;百舌吶喊的夜晚&quot; href=&quot;http://book.douban.com/subject/1862497/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://img3.douban.com/spic/s6801526.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; /&gt;&lt;/a&gt; &lt;a style=&quot;float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;&quot; title=&quot;新參者&quot; href=&quot;http://book.douban.com/subject/6535522/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://img3.douban.com/spic/s6643996.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; /&gt;&lt;/a&gt; &lt;a style=&quot;float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;&quot; title=&quot;Fate/Zero Vol.1 [第四次圣杯战争秘话]&quot; href=&quot;http://book.douban.com/subject/3908784/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://img1.douban.com/spic/s4499191.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div id=&quot;_mcePaste&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;东野圭吾《新参者》&lt;/strong&gt;：带有主线的短篇集，东野今年在华语地区出版的最好的一本。本来对加贺刑警系列（为什么要专门写成刑警系列……一定不是《便当》的影响）并不感兴趣，但此本改变了我的想法。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;虚渊玄《Fate/Zero》&lt;/strong&gt;：爱的战士真的有两把刷子，比起Fate/Zero来说，Fate Stay/Night就是青春偶像剧了。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;若竹七海《我的日常推理》&lt;/strong&gt;：被喜欢/厌恶两个极端明显的一部推理作品，有人认为诡计是故弄玄虚，有人觉得喔喔喔这个安排简直超神了。我最喜欢里面利用虚拟的“公司杂志”目录作为章节分隔的做法。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;小酒井不木《恋爱曲线》&lt;/strong&gt;：日本侵华战前的推理集子，其时髦程度放在现在也很高，整本读下来非常痛快。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;奈須きのこ《空之境界》&lt;/strong&gt;：先看的动画剧场版，文字的力度甚至强于直观的画面表现。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;逢坂刚《百舌呐喊的夜晚》&lt;/strong&gt;：够冷够硬但又好读，简体也要买本！&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2&gt;其他类别的书籍推荐&lt;/h2&gt;
&lt;p&gt;&lt;a style=&quot;float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;&quot; title=&quot;中国民间崇拜&quot; href=&quot;http://book.douban.com/subject/3702365/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://img3.douban.com/spic/s4139177.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; /&gt;&lt;/a&gt; &lt;a style=&quot;float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;&quot; title=&quot;神奇的二维国&quot; href=&quot;http://book.douban.com/subject/3530171/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://img3.douban.com/spic/s3699638.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; /&gt;&lt;/a&gt; &lt;a style=&quot;float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;&quot; title=&quot;汇编语言&quot; href=&quot;http://book.douban.com/subject/1215178/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://img1.douban.com/spic/s4448052.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; /&gt;&lt;/a&gt; &lt;a style=&quot;float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;&quot; title=&quot;夹边沟记事&quot; href=&quot;http://book.douban.com/subject/3239549/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://img1.douban.com/spic/s3294692.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; /&gt;&lt;/a&gt; &lt;a style=&quot;float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;&quot; title=&quot;虚拟书评&quot; href=&quot;http://book.douban.com/subject/4915930/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://img3.douban.com/spic/s4418003.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; /&gt;&lt;/a&gt; &lt;a style=&quot;float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;&quot; title=&quot;徒然草·方丈记&quot; href=&quot;http://book.douban.com/subject/6877560/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://img3.douban.com/spic/s6962253.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; /&gt;&lt;/a&gt; &lt;a style=&quot;float: left; font-family: 'Microsoft Yahei', 'Microsoft Jhenghei', Arial; line-height: normal; background-color: rgba(255, 255, 255, 0.0976563); font-size: medium;&quot; title=&quot;CLR via C#&quot; href=&quot;http://book.douban.com/subject/4112979/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://img3.douban.com/spic/s4254428.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;禄是遒《中国民间迷信（崇拜）》系列&lt;/strong&gt;：徐家汇藏书楼的良心作，虽然每本都是薄薄200-300页卖到40块，但总体来说是一套很有趣的风俗讲解和记录丛书。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;艾伯特《神奇的二维国》&lt;/strong&gt;：小说形式的科普读物，要考虑到这是1884年的作品，那只有用“神作”才能形容。希望大家都读读，为适应二向箔打击带来的新世界做好准备。另外推荐给妄图二次元去把虚拟妹子的2D厨。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;杨显惠《夹边沟记事》&lt;/strong&gt;：神作。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;王爽《汇编语言》&lt;/strong&gt;：从未见过一本语言类教程能写得如此让人看完一章还想看下一章。在遇到此书之前数次学习汇编都是半懂。用了半个月的业余时间看完后顺利入门。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;比目鱼《虚拟书评》&lt;/strong&gt;：之前在比目鱼Blog上看到这种形式的文章，太好玩了。见到此书变为实体还以为也是虚拟的……&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;王新禧译本《徒然草·方丈记》&lt;/strong&gt;：王老师文笔真是巨好——除巨好以外我词穷找不出其他可形容的了——古风浓郁但又读起来不晦涩 （当然是对于我这种古文门外汉来说） ，实是译文典范。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jeffrey Richter《CLR via C#》&lt;/strong&gt;：夯实基础的必备知识，对于.net程序员来说不是只知道string有多少方法就行了。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;雷区&lt;/h2&gt;
&lt;p&gt;既然有推荐肯定也有扫雷：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;内田康夫《贵宾室的怪客》&lt;/li&gt;
&lt;li&gt;东野圭吾《以眨眼干杯》。骗版税代表作。看完《新参者》再看这部，都会以为“东野圭吾”是个拥有数名文风迥异水平有天地之差的作家的写作团体。&lt;/li&gt;
&lt;li&gt;麦家《风语》系列。作为麦家的死忠读者，我都以为买到盗名之作了。&lt;/li&gt;
&lt;li&gt;二阶堂雷人老师的一切作品，以《双面兽事件》为代表。&lt;/li&gt;
&lt;/ul&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/597572839/siwei/feedsky/s.gif?r=http://wei.si/blog/2011/12/reading-summary-2011/&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</content:encoded><wfw:commentRss>http://wei.si/blog/2011/12/reading-summary-2011/feed/</wfw:commentRss><slash:comments>0</slash:comments><description>终于到了2011最后一天，可以发各种总结了。阅读还是用http://imnerd.org/douban/进行统计。
题外话：动画和游戏
至于动画、游戏什么的，自然用Bangumi的年鉴功能。懒得单发，记录在此了：
「Bangumi 2011 年鉴」 2011 年，我看了 28 部动画，读了 本书，听了 1 张音乐，玩了 7 部游戏，看了 1 部剧集，参与了 73 次讨论，进行了 0 次条目编辑。
在这28部动画中印象最深刻的是还在放送的《ちはやふる》（歌牌情缘），游戏里面觉得最好的是一款老游戏《枪声与钻石》。当然今年玩游戏太少了，而且基本都是PSP上的AVG，最近这三个月已经写了大概四篇相关的玩后体会。
数据
回到正题，2011年的阅读数量为112，较之前年回落较多。原因不外乎是工作太忙，另外则是去掉了漫画，轻小说也只保留第一卷，确保统计水分不太大。

尽管如此，其实这112本书中有80%还是推理小说/轻小说，专业书以及学习类书籍大概只有10本……？所以推荐列表还是从推理小说开始吧（书籍链接在图片上）。
推荐的推理小说/轻小说类作品
     


东野圭吾《新参者》：带有主线的短篇集，东野今年在华语地区出版的最好的一本。本来对加贺刑警系列（为什么要专门写成刑警系列……一定不是《便当》的影响）并不感兴趣，但此本改变了我的想法。
虚渊玄《Fate/Zero》：爱的战士真的有两把刷子，比起Fate/Zero来说，Fate Stay/Night就是青春偶像剧了。
若竹七海《我的日常推理》：被喜欢/厌恶两个极端明显的一部推理作品，有人认为诡计是故弄玄虚，有人觉得喔喔喔这个安排简直超神了。我最喜欢里面利用虚拟的“公司杂志”目录作为章节分隔的做法。
小酒井不木《恋爱曲线》：日本侵华战前的推理集子，其时髦程度放在现在也很高，整本读下来非常痛快。
奈須きのこ《空之境界》：先看的动画剧场版，文字的力度甚至强于直观的画面表现。
逢坂刚《百舌呐喊的夜晚》：够冷够硬但又好读，简体也要买本！



其他类别的书籍推荐
      

禄是遒《中国民间迷信（崇拜）》系列：徐家汇藏书楼的良心作，虽然每本都是薄薄200-300页卖到40块，但总体来说是一套很有趣的风俗讲解和记录丛书。
艾伯特《神奇的二维国》：小说形式的科普读物，要考虑到这是1884年的作品，那只有用“神作”才能形容。希望大家都读读，为适应二向箔打击带来的新世界做好准备。另外推荐给妄图二次元去把虚拟妹子的2D厨。
杨显惠《夹边沟记事》：神作。
王爽《汇编语言》：从未见过一本语言类教程能写得如此让人看完一章还想看下一章。在遇到此书之前数次学习汇编都是半懂。用了半个月的业余时间看完后顺利入门。
比目鱼《虚拟书评》：之前在比目鱼Blog上看到这种形式的文章，太好玩了。见到此书变为实体还以为也是虚拟的……
王新禧译本《徒然草·方丈记》：王老师文笔真是巨好——除巨好以外我词穷找不出其他可形容的了——古风浓郁但又读起来不晦涩 （当然是对于我这种古文门外汉来说） ，实是译文典范。
Jeffrey Richter《CLR via C#》：夯实基础的必备知识，对于.net程序员来说不是只知道string有多少方法就行了。

雷区
既然有推荐肯定也有扫雷：

内田康夫《贵宾室的怪客》
东野圭吾《以眨眼干杯》。骗版税代表作。看完《新参者》再看这部，都会以为“东野圭吾”是个拥有数名文风迥异水平有天地之差的作家的写作团体。
麦家《风语》系列。作为麦家的死忠读者，我都以为买到盗名之作了。
二阶堂雷人老师的一切作品，以《双面兽事件》为代表。&lt;img src=&quot;http://www1.feedsky.com/t1/597572839/siwei/feedsky/s.gif?r=http://wei.si/blog/2011/12/reading-summary-2011/&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</description><category>读书</category><pubDate>Sat, 31 Dec 2011 00:37:43 +0800</pubDate><author>Si Wei</author><comments>http://wei.si/blog/2011/12/reading-summary-2011/#comments</comments><guid isPermaLink="false">http://wei.si/blog/?p=643564</guid><dc:creator>Si Wei</dc:creator><fs:srclink>http://wei.si/blog/2011/12/reading-summary-2011/</fs:srclink><fs:srcfeed>http://wei.si/blog/feed/</fs:srcfeed><fs:itemid>feedsky/siwei/~8249691/597572839/1229498</fs:itemid></item><item><title>《深度探索C++对象模型》学习笔记（5-7章）</title><link>http://wei.si/blog/2011/12/inside-com-study-notes-5-7/</link><content:encoded>&lt;h2&gt;第5章 构造析构和拷贝&lt;/h2&gt;
&lt;h3&gt;虚函数&lt;/h3&gt;
&lt;p&gt;对于抽象类而言，是否应该自己负责初始化类内的数据成员？（别忘了抽象类也可以有非纯虚函数和数据成员）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一般情况下被认为子类要负责从基类继承来的数据成员的初始化&lt;/li&gt;
&lt;li&gt;或者基类必须提供一个显式的构造函数用于自己数据成员的初始化&lt;/li&gt;
&lt;li&gt;最好的方法则是将行为和数据分离，提供接口专门用于定义方法&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;cpp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;class&lt;/span&gt; A_B
&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt;
    &lt;span style=&quot;color: #0000ff;&quot;&gt;virtual&lt;/span&gt; ~A_B&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #000080;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #0000dd;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
    &lt;span style=&quot;color: #0000ff;&quot;&gt;virtual&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;void&lt;/span&gt; Say&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #000080;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #0000dd;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
    &lt;span style=&quot;color: #0000ff;&quot;&gt;inline&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;char&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color: #000040;&quot;&gt;*&lt;/span&gt; GetData&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;return&lt;/span&gt; iData&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;protected&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt;
    A_B&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color: #000040;&quot;&gt;*&lt;/span&gt; aData &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt; iData&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt; aData &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt;  &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;protected&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt;
    &lt;span style=&quot;color: #0000ff;&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color: #000040;&quot;&gt;*&lt;/span&gt; iData&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;inline&lt;/span&gt; A_B&lt;span style=&quot;color: #008080;&quot;&gt;::&lt;/span&gt;~A_B&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
&lt;span style=&quot;color: #0000ff;&quot;&gt;class&lt;/span&gt; C_D &lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt; A_B &lt;span style=&quot;color: #666666;&quot;&gt;// concrete derived class&lt;/span&gt;
&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt;
    C_D&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color: #000040;&quot;&gt;*&lt;/span&gt; aData, &lt;span style=&quot;color: #0000ff;&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color: #000040;&quot;&gt;*&lt;/span&gt; aData2 &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt;
           A_B&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt; aData &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt;, iData2&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt; aData2 &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #0000dd;&quot;&gt;cout&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;&amp;quot;c_d ctor&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;endl&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt;
    &lt;span style=&quot;color: #0000ff;&quot;&gt;virtual&lt;/span&gt; ~C_D&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #0000dd;&quot;&gt;delete&lt;/span&gt; iData2&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt;
    &lt;span style=&quot;color: #0000ff;&quot;&gt;virtual&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;void&lt;/span&gt; Say&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #0000dd;&quot;&gt;cout&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;&amp;quot;c_d says: &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;iData&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;endl&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt;
    &lt;span style=&quot;color: #0000ff;&quot;&gt;void&lt;/span&gt; Say2&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #0000dd;&quot;&gt;cout&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;&amp;quot;c_d says2: &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;iData2&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;endl&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt;
    &lt;span style=&quot;color: #0000ff;&quot;&gt;char&lt;/span&gt;&lt;span style=&quot;color: #000040;&quot;&gt;*&lt;/span&gt; iData2&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;纯虚函数&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;拥有定义的纯虚函数（这还叫纯虚函数么）可以在子类中进行调用。不过就是什么用都没有罢了。&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;cpp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;//定义&lt;/span&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;inline&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;void&lt;/span&gt; A_B&lt;span style=&quot;color: #008080;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #007788;&quot;&gt;Say&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #0000dd;&quot;&gt;cout&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;&amp;quot;hey!&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt;
&lt;span style=&quot;color: #666666;&quot;&gt;//调用，发现hey!并没有打印出来&lt;/span&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;virtual&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;void&lt;/span&gt; Say&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt; A_B&lt;span style=&quot;color: #008080;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #007788;&quot;&gt;Say&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #0000dd;&quot;&gt;cout&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;&amp;quot;c_d says: &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;iData&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;endl&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;实际上是否让纯虚函数拥有（没用的）定义由程序员说了算。&lt;/li&gt;
&lt;li&gt;但唯一的例外是纯虚析构函数，必须像上面那样进行显式定义 A_B::~A_B() {}
&lt;ul&gt;
&lt;li&gt;否则就会出现错误，严格来说并非编译错误，而是链接错误。&lt;/li&gt;
&lt;li&gt;原因很简单，析构函数和构造函数一样，子类的都会由编译器进行扩充，调用基类的版本。&lt;/li&gt;
&lt;li&gt;不希望这么定义的话，解决方法只有生命非纯虚的析构函数&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Virtual Specification&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不加选择地将函数设定为virtual在效率上会不升反降，不能依赖编译器的优化&lt;/li&gt;
&lt;li&gt;应付const也会令人头疼，例如在基类中不需要修改的const ref或者const pointer，到了子类就需要修改了。目前最好的方法是不用const（……无语）&lt;/li&gt;
&lt;li&gt;需要考虑到的（不全）
&lt;ul&gt;
&lt;li&gt;抽象类的构造函数需要负责初始化自己的数据成员，可以声明为protected避免外部访问&lt;/li&gt;
&lt;li&gt;缺少多态需求的函数不要设定为virtual，尤其是inline函数&lt;/li&gt;
&lt;li&gt;慎用const，除非确定派生类也不会修改const修饰的对象&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;span id=&quot;more-643514&quot;&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3&gt;对象构造&lt;/h3&gt;
&lt;p&gt;无继承情况下的对象构造（限于一个class内都是public访问级别的对象）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;class B { public: int a, b, c; }&lt;/li&gt;
&lt;li&gt;C中的全局变量会被视为“临时性的定义”而只保留一个实体，位于DS的末端，称为BSS（Block Started by Symbol）的区域&lt;/li&gt;
&lt;li&gt;对于new和delete运算符的操作，不会触发trivial构造函数和析构函数&lt;/li&gt;
&lt;li&gt;而传值方式的return操作，感觉上会触发trivial copy constructor，但实际上只是位拷贝&lt;/li&gt;
&lt;li&gt;显式地设定类对象的数据成员值如何？例如B b; b.a = 1; b.b = &amp;#8230;
&lt;ul&gt;
&lt;li&gt;效率不如初始化列表高&lt;/li&gt;
&lt;li&gt;而且所设定的成员访问范围只能是public&lt;/li&gt;
&lt;li&gt;但也不是一无是处。对于大数据量、常量赋值的情况，显示设定数据的方式反而效率更高一点&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;多了private接口和inline的构造函数，但无virtual特性&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;class B { public: B ( int aA = 0, int aB = 0, int aC = 0 ) : a(aA), b(aB), c(aC) {} private: int a, b, c; }&lt;/li&gt;
&lt;li&gt;大小不会变化，默认的构造函数、析构函数和拷贝构造也够用了。提供初始化列表会比较高效&lt;/li&gt;
&lt;li&gt;编译器会进行优化，将inline的构造函数在对象声明处（不是构造函数内！）展开为显示设定成员的方式，利用常量赋值&lt;/li&gt;
&lt;li&gt;new运算符则会有些变化 B* b = __operator_new( sizeof (B) ); if ( b != NULL ) then b-&gt;B::B(); 多了一个指针大小非零的判断&lt;/li&gt;
&lt;li&gt;而其他的，例如delete运算符、传值返回等，和上面的一样&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;多了virtual函数的引入&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;class B { public: B ( int aA = 0, int aB = 0 ) : a(aA), b(aB) {} virtual int C(); private: int a, b, c; }&lt;/li&gt;
&lt;li&gt;最先想到的：每一个B对象都会有一个vptr指向vtbl，这个vptr占用一个字长。这种额外消耗是否值得要看多态所带来的价值是否大于vptr所带来的空间消耗&lt;/li&gt;
&lt;li&gt;其他的代价
&lt;ul&gt;
&lt;li&gt;构造函数会自动被添加代码，用于初始化vptr。这些代码位于所有的基类构造函数之后、程序员的代码之前。（展开后）类似于&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;cpp&quot; style=&quot;font-family:monospace;&quot;&gt;B&lt;span style=&quot;color: #000040;&quot;&gt;*&lt;/span&gt; B&lt;span style=&quot;color: #008080;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #007788;&quot;&gt;B&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt; B&lt;span style=&quot;color: #000040;&quot;&gt;*&lt;/span&gt; &lt;span style=&quot;color: #0000dd;&quot;&gt;this&lt;/span&gt;, &lt;span style=&quot;color: #0000ff;&quot;&gt;int&lt;/span&gt; aA, &lt;span style=&quot;color: #0000ff;&quot;&gt;int&lt;/span&gt; aB &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt;
&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt;
this&lt;span style=&quot;color: #000040;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;gt;&lt;/span&gt;__vptr_point &lt;span style=&quot;color: #000080;&quot;&gt;=&lt;/span&gt; __vtbl_point&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
this&lt;span style=&quot;color: #000040;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;gt;&lt;/span&gt;a &lt;span style=&quot;color: #000080;&quot;&gt;=&lt;/span&gt; aA&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
this&lt;span style=&quot;color: #000040;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;gt;&lt;/span&gt;b &lt;span style=&quot;color: #000080;&quot;&gt;=&lt;/span&gt; aB&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #0000dd;&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;不再为trivial的拷贝构造函数和拷贝运算符函数（但隐式的析构函数仍然是trivial的）
&lt;ul&gt;
&lt;li&gt;类似于构造函数，需要拷贝vptr以及相关的数据成员（参看“构造函数：拷贝构造函数”），有可能是非bitwisely copy。这也是需要编译器合成不再trivial的拷贝函数（运算符）的原因之一。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;另外一个原因则是返回值的需要。作为引用参数之一的返回值需要拷贝构造函数获得vptr，同时销毁局部变量。&lt;/li&gt;
&lt;li&gt;由此引出的想法：有关显式拷贝构造函数的必要性——大量传值返回某类的情况下。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a name=&quot;.E6.9C.89.E7.BB.A7.E6.89.BF.E5.AF.B9.E8.B1.A1.E6.9E.84.E9.80.A0&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;有继承对象构造&lt;/h3&gt;
&lt;p&gt;回顾：构造函数的工作&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果有的话，调用所有虚基类构造函数&lt;/li&gt;
&lt;li&gt;如果有基类的话，调用基类的构造器。如果有多个基类，调用顺序为声明的顺序
&lt;ul&gt;
&lt;li&gt;位于构造列表里面的，直接以参数进行调用&lt;/li&gt;
&lt;li&gt;并非位于列表里面的，调用默认的构造函数&lt;/li&gt;
&lt;li&gt;如果是多重继承的基类，那么需要进行this指针的调整&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;初始化vptr指向相应的vtbl&lt;/li&gt;
&lt;li&gt;函数初始化列表会被编译器展开放置于构造函数之中（参见2.3）&lt;/li&gt;
&lt;li&gt;没有位于列表中的数据成员，如果拥有默认构造器，那么需要进行调用&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;拷贝构造函数中“自我拷贝”检查的必要性&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;并非大问题，但在B b1; b2 = b1; b1 = b2;情况下，如果没有进行this指针的检查，类似的操作会导致额外的开销&lt;/li&gt;
&lt;li&gt;目前的编译器都不会对此进行检查，需要程序员进行自律&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;有继承情况下的对象构造，虚拟继承&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;回顾：虚拟继承需要添加虚基类子对象（virtual base class subobject），几种解决方式（参见3.3）&lt;/li&gt;
&lt;li&gt;在虚拟继承中单纯地对每一个构造函数进行扩充是不可行的。
&lt;ul&gt;
&lt;li&gt;需要增加一个是否为最底层对象的检查，如果是才负责初始化从最上层基类所继承下来的数据成员。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;vptr初始化&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;cpp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;class&lt;/span&gt; Base &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;virtual&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;void&lt;/span&gt; Info&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #0000dd;&quot;&gt;cout&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;&amp;quot;base::info&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;endl&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;protected&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;int&lt;/span&gt; iBaseValue&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;class&lt;/span&gt; Derive1 &lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;virtual&lt;/span&gt; Base &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;virtual&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;void&lt;/span&gt; Info&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #0000dd;&quot;&gt;cout&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;&amp;quot;derived1::info&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;endl&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;protected&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;int&lt;/span&gt; iDerive1Value&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;class&lt;/span&gt; Derive2 &lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;virtual&lt;/span&gt; Base &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;virtual&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;void&lt;/span&gt; Info&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #0000dd;&quot;&gt;cout&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;&amp;quot;derived2::info&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;endl&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;protected&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;int&lt;/span&gt; iDerive2Value&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;class&lt;/span&gt; DD &lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt; Derive1, &lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt; Derive2 &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;virtual&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;void&lt;/span&gt; Info&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #0000dd;&quot;&gt;cout&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;&amp;quot;dd::info&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;endl&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;protected&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;int&lt;/span&gt; iDDValue&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;class&lt;/span&gt; DDD &lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt; DD &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;virtual&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;void&lt;/span&gt; Info&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #0000dd;&quot;&gt;cout&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;&amp;quot;ddd::info&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;endl&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;int&lt;/span&gt; iDDDValue&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;基类指针指向的子类对象，调用的函数实体为子类对象的&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;cpp&quot; style=&quot;font-family:monospace;&quot;&gt;   DDD ddd&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
   Derive1 d1&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
   Base&lt;span style=&quot;color: #000040;&quot;&gt;*&lt;/span&gt; b &lt;span style=&quot;color: #000080;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #000040;&quot;&gt;&amp;amp;&lt;/span&gt;amp&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;ddd&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
   b&lt;span style=&quot;color: #000040;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;gt;&lt;/span&gt;Info&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #666666;&quot;&gt;//&amp;quot;ddd::info&amp;quot;&lt;/span&gt;
   b &lt;span style=&quot;color: #000080;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #000040;&quot;&gt;&amp;amp;&lt;/span&gt;amp&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;d1&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
   b&lt;span style=&quot;color: #000040;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;gt;&lt;/span&gt;Info&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #666666;&quot;&gt;//&amp;quot;derived1::info&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;如果在构造函数中调用成员函数会如何？构造一个子类对象时候，每次的构造函数会被认为是调用最底层子类的还是当前类本身的？
&lt;ul&gt;
&lt;li&gt;当然是类本身的！因为构造的时候是按照从上到下的顺序。derive1构造的时候，ddd还尚未在内存中出现，更不要提它继承出来的Info函数了&lt;/li&gt;
&lt;li&gt;同时这也是构造函数不可为虚函数的一个原因（抽象工厂除外）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;cpp&quot; style=&quot;font-family:monospace;&quot;&gt;base&lt;span style=&quot;color: #008080;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #007788;&quot;&gt;info&lt;/span&gt;
derived1&lt;span style=&quot;color: #008080;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #007788;&quot;&gt;info&lt;/span&gt;
derived2&lt;span style=&quot;color: #008080;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #007788;&quot;&gt;info&lt;/span&gt;
dd&lt;span style=&quot;color: #008080;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #007788;&quot;&gt;info&lt;/span&gt;
ddd&lt;span style=&quot;color: #008080;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #007788;&quot;&gt;info&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;再考虑一种情况，如果Info()又调用了一个虚函数，例如VF()会如何？按照上面第二条的说法，运行时应该调用的是子类的函数。但构造时候很明显会调用基类的
&lt;ul&gt;
&lt;li&gt;实验的结果是，构造函数时候调用了各个基类自己的VF()，而运行的时候不出所料，就算用Base*指向了子类对象，调用的也是ddd::VF()。&lt;/li&gt;
&lt;li&gt;编译器的做法是对于在构造函数中的虚函数调用进行特殊处理，声明为静态方式的调用，不要用虚拟特性解决&lt;/li&gt;
&lt;li&gt;说起来简单，但实际上编译器所做的工作要复杂得多，首先要通过vptr拿到vtbl，获取虚函数的列表，这些函数都是在构造函数调用中不能表现出虚拟特性的&lt;/li&gt;
&lt;li&gt;由此而衍生出的问题是vptr的初始化时间。显然要早于任何程序员写在构造函数中的代码，但要晚于vtbl和基类构造函数的创建&lt;/li&gt;
&lt;li&gt;通过这么多学习，再次回顾构造函数步骤时候会觉得比之前要清晰很多，显然我们在构造一个基类的时候，首先要考虑虚拟继承的情况，判断自己是否为最底层的子类，如果是的话要负责构造基类；之后按照顺序构造所有基类；接下来根据基类的信息拿到vtbl中的虚函数列表；最后执行程序员自己写的代码&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;构造函数初始化列表中调用虚函数是否安全？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;形如 Derived( int aValue, int aValue2 ) : Base( F( aValue ) ), iValue ( aValue2 ) { } // F为虚函数&lt;/li&gt;
&lt;li&gt;分情况讨论。如果不需要对基类在初始化列表中同样进行初始化，那么应该是安全的。考虑一下，vptr在此时应该已经设置完毕，展开初始化列表的时候，虚函数可以正确地通过指针拿到。当然有一点需要注意的是被调用的虚函数可能会使用没有初始化的数据成员，但这不是我们讨论的问题了。所以结论是，OK，没问题，只是不推荐这么做而已。&lt;/li&gt;
&lt;li&gt;如果需要在初始化列表中对基类进行初始化，那么是绝对不安全的！基类的构造要早于子类的函数被创建，但在初始化列表展开之前，基类构造的时候就要使用子类虚函数的话，很显然是行不通的：有可能指向定义这个函数的vtbl的vptr尚未创建成功，或者可能指向了错误的类对象。（不过在gcc上貌似没有什么问题）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a name=&quot;.E6.8B.B7.E8.B4.9D.E5.92.8C.E8.B5.8B.E5.80.BC&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;拷贝和赋值&lt;/h3&gt;
&lt;p&gt;依然先要回顾一下&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;什么时候编译器会生成一个默认的拷贝构造函数？需要的时候，但并非所有情况（参见2.2）&lt;/li&gt;
&lt;li&gt;是否需要自己写拷贝构造函数需要斟酌。对于bitwise copy足够的情况没有必要自己编写&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对于拷贝运算符来说以下情况是不会进行Bitwise copy的（同样参见2.2构造函数：拷贝构造函数）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数据成员中有拥有拷贝运算符的类型&lt;/li&gt;
&lt;li&gt;基类中有拷贝运算符&lt;/li&gt;
&lt;li&gt;类中有虚函数（因为等号右边的对象可能是个子类）&lt;/li&gt;
&lt;li&gt;继承自虚基类&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;其实就是一句话……如果默认的bitwise copy（memberwise assignment）不能满足需要的时候，会出现默认的拷贝运算符 如果默认的也不能满足需要，那就得自己写一个拷贝运算符进行深拷贝 编译器在需要的时候会生成拷贝运算符&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;生成出来的类似于：&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;cpp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;inline&lt;/span&gt; D&lt;span style=&quot;color: #000040;&quot;&gt;&amp;amp;&lt;/span&gt;amp&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; D&lt;span style=&quot;color: #008080;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #007788;&quot;&gt;operator&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt; D&lt;span style=&quot;color: #000040;&quot;&gt;*&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #0000dd;&quot;&gt;this&lt;/span&gt;, D&lt;span style=&quot;color: #000040;&quot;&gt;&amp;amp;&lt;/span&gt;amp&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; rhs &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt;
&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt;
this&lt;span style=&quot;color: #000040;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;gt;&lt;/span&gt;B&lt;span style=&quot;color: #008080;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #007788;&quot;&gt;operator&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt; rhs &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
iValue &lt;span style=&quot;color: #000080;&quot;&gt;=&lt;/span&gt; rhs.&lt;span style=&quot;color: #007788;&quot;&gt;Value&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #0000dd;&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;可惜只能这么做，因为没有一个类似于构造函数一样的“拷贝初始化列表”&lt;/li&gt;
&lt;li&gt;通过this指针取到基类运算符进行赋值也可以用这个代替： ( *(B*)this) ) = rhs;，这样转化成了通过基类指针对对象进行值拷贝&lt;/li&gt;
&lt;li&gt;关键问题就在于怎么拿到基类的运算符重载函数，另外则是如果有多继承的情况，如何只（在最底层的子类）执行一次拷贝操作？
&lt;ul&gt;
&lt;li&gt;嗯……通过指向成员函数的指针：&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;cpp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;typedef&lt;/span&gt; B&lt;span style=&quot;color: #000040;&quot;&gt;&amp;amp;&lt;/span&gt;amp&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;B&lt;span style=&quot;color: #008080;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #000040;&quot;&gt;*&lt;/span&gt;POF&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;const&lt;/span&gt; B&lt;span style=&quot;color: #000040;&quot;&gt;&amp;amp;&lt;/span&gt;amp&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
POF pOF &lt;span style=&quot;color: #000080;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #000040;&quot;&gt;&amp;amp;&lt;/span&gt;amp&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;B&lt;span style=&quot;color: #008080;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #007788;&quot;&gt;operator&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
D.&lt;span style=&quot;color: #000040;&quot;&gt;*&lt;/span&gt;pOF&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt; anotherD &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;其丑无比！&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;其实很多编译器在虚继承的时候处理拷贝运算符比较苦手&lt;/li&gt;
&lt;li&gt;所以最简单的方式就是执行多次拷贝，只要保证当前类的调用位于所有的基类之后就行——虽然这样一来虚基类子对象会复制多次&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a name=&quot;.E6.9E.90.E6.9E.84&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;析构&lt;/h3&gt;
&lt;p&gt;同构造函数、拷贝函数的情况类似，析构函数只有在需要的时候（基类有析构函数、数据成员有析构函数）的情况下才被生成出来 顺序和构造函数正好相反&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;析构函数执行程序员的代码&lt;/li&gt;
&lt;li&gt;如果类的数据成员拥有析构函数，那么也会调用，不过顺序和声明相反&lt;/li&gt;
&lt;li&gt;对象内有vptr的话，那么重设vtbl&lt;/li&gt;
&lt;li&gt;如果基类拥有析构函数的话，同样相反调用&lt;/li&gt;
&lt;li&gt;如果虚基类拥有析构函数的话，且当前类是最底层的子类，那么同样相反调用&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;整个过程类似“脱壳”一样，从下至上地析构，子类逐渐地变为上层基类、上上层基类、上上上层……（如果有的话） 两种析构函数的版本&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;完整的对象，设置vptrs，调用虚基类的析构函数&lt;/li&gt;
&lt;li&gt;基类子对象，除非析构函数中调用了虚函数，否则不会设置vptrs、调用虚基类的析构函数&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a name=&quot;.E7.AC.AC6.E7.AB.A0_.E6.89.A7.E8.A1.8C.E6.9C.9F&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;第6章 执行期&lt;/h2&gt;
&lt;p&gt;&lt;a name=&quot;.E6.9E.84.E9.80.A0.E5.92.8C.E6.9E.90.E6.9E.84&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;构造和析构&lt;/h3&gt;
&lt;p&gt;局部对象的构造析构&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对于switch/case、goto等指令析构函数可能会被安排出现多次：每个函数的退出点都需要有一个&lt;/li&gt;
&lt;li&gt;但位于局部对象声明之前的，不需要&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;全局对象&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;全局对象的生存期为main()之前构造而函数结束前析构&lt;/li&gt;
&lt;li&gt;放置的位置为DS（5.2构析拷贝：对象构造）&lt;/li&gt;
&lt;li&gt;为了支持类对象的静态初始化，需要在有虚继承的情况下进行指针调整，将子类中vbc pointer的正确位置返回&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;局部对象&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;局部静态对象声明一次，只会初始化和销毁一次。初始化的地点和全局对象一样，即时对象所在的函数并未被调用&lt;/li&gt;
&lt;li&gt;闭包的概念。&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;cpp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;void&lt;/span&gt; foo2&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;int&lt;/span&gt; i &lt;span style=&quot;color: #000080;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #0000dd;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #0000dd;&quot;&gt;cout&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;i&lt;span style=&quot;color: #000040;&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;endl&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
    foo2&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #666666;&quot;&gt;// 0&lt;/span&gt;
    foo2&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #666666;&quot;&gt;// 1&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;数组&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果数组元素没有显式的构造函数和析构函数，那么分配足够的空间就够了&lt;/li&gt;
&lt;li&gt;但如果有的话，参考cfront的解法，定义一个新的函数vec_new，参数分别为数组起始地址、类对象大小、数组元素个数、构造函数和析构函数的指针
&lt;ul&gt;
&lt;li&gt;与之对应的数组析构函数vec_del只接受一个析构函数指针就足够，然后针对所有元素遍历调用&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;例如B bases[10];就会变为 vec_new( &amp;amp;bases, sizeof( B ), 10, B::B, 0 );，函数会对于传入的所有对象分别调用其构造和析构函数
&lt;ul&gt;
&lt;li&gt;程序员提供了初始值的情况呢？例如 B bases[10] = { B(), B( 1 ), 2 };&lt;/li&gt;
&lt;li&gt;编译器会解析出已经赋值的部分，将其变为构造函数的调用，再对剩余的对象调用vec_new，当然，数组起始地址和元素个数都会不同&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;大概类似于B::B( &amp;amp;bases[0], 0 ); B::B( &amp;amp;bases[1], 1 ); B::B( &amp;amp;bases[2], 2 ); vec_new( &amp;amp;bases+3, sizeof( B ), 7, B::B, 0 );
&lt;ul&gt;
&lt;li&gt;cfront 2.0之前，数组无法应付超过一个默认参数的构造函数或者默认构造函数，回顾上面的vec_new函数，我们如何调用到拥有多个默认参数的构造函数指针？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;cfront的编译器多加了一个stub的构造函数（同样也是没有参数），里面调用程序员写的带有多个默认参数的构造函数&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;new.E5.92.8Cdelete&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;new和delete&lt;/h3&gt;
&lt;p&gt;new运算符&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;简单的一个new运算符语句其实包括多个步骤。例如int* pi = new int( 5 );
&lt;ol&gt;
&lt;li&gt;首先调用__new函数进行内存分配int* pi = __new ( sizeof(int ) );&lt;/li&gt;
&lt;li&gt;赋值 *pi = 5。&lt;/li&gt;
&lt;li&gt;实际上第一步中应该多判断一下pi是否不为0再赋值&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;对于类对象来说。例如Base* pb = new Base( pb, 5 );
&lt;ol&gt;
&lt;li&gt;类似于上面的做法，分配内存先 Base* pb; pb = __new( sizeof( B ) );&lt;/li&gt;
&lt;li&gt;赋值 *pb = Base::Base( 5 );&lt;/li&gt;
&lt;li&gt;实际情况需要考虑的还要更多，例如在拷贝构造的时候，函数有可能抛出异常。如果catch到的话需要__delete掉已经分配的内存空间&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;delete运算符&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;也是交给内置函数去做的。例如delete pi;
&lt;ol&gt;
&lt;li&gt;变为if ( pi != 0 ) __delete( pi );&lt;/li&gt;
&lt;li&gt;不过由于不会重置内存，所以之后再判断pi是否为null甚至*p去取值都有可能成功。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;对于类对象的析构来说。例如delete pb;
&lt;ol&gt;
&lt;li&gt;变为if ( pb != 0 ) { Base::~Base( pb ); __delete( pb ); }&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;new和delete运算符的实现&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;首先是size为0的情况会自动调整为1，这是因为每一次new出来的指针都应该是不同的，所以就算size为0，也要指向不同的1-byte内存区域。&lt;/li&gt;
&lt;li&gt;声明void*指针，用malloc拿到相应size的空间并且返回指针&lt;/li&gt;
&lt;li&gt;delete采用free()实现&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;数组的new运算符&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;例如int* pi = new int[5]; 或者MyStruct* ps = new MyStruct[5]; //MyStruct是结构体
&lt;ul&gt;
&lt;li&gt;内置类型时vec_new并不会调用，因为它作用就是遍历调用构造函数，但上面两种类型都没有&lt;/li&gt;
&lt;li&gt;只有__new用来分配空间&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;对于拥有默认构造器的类来说，数组初始化时候也需要析构函数指针，因为可能发生异常，以便清理已经分配的空间（6.1执行期：构造和析构第4节）&lt;/li&gt;
&lt;li&gt;C++ 2.0之前在delete掉数组时候，需要程序员手动指定元素个数，例如delete [5] pi;
&lt;ul&gt;
&lt;li&gt;但之后就不用了，就像我们现在所使用的那样delete[] pi;&lt;/li&gt;
&lt;li&gt;实现这个功能需要知道数组首地址和元素的个数。但这样做需要更多性能上的开销。所以如果没带[]调用delete，只会删掉一个元素&lt;/li&gt;
&lt;li&gt;具体来说，即将vec_new返回的内存地址多加一个word长度的信息，保存数组长度（所谓cookie）&lt;/li&gt;
&lt;li&gt;但Sun编译器的做法是维护一个保存数组指针和大小的额外数组，其中还放置析构函数的地址&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;继承情况下的问题
&lt;ul&gt;
&lt;li&gt;D继承于B，都实现了虚析构函数。那么B* pb = new D[ 5 ];如何？&lt;/li&gt;
&lt;li&gt;语法上OK，但delete [] pb时候问题来了……vec_del只会调用5次B类的析构函数，D的却没有。因为它总是执行被删除类型的析构函数。
&lt;ul&gt;
&lt;li&gt;vec_del只会调用5次B类的析构函数，D的却没有。因为它总是执行被删除类型的析构函数。&lt;/li&gt;
&lt;li&gt;更可怕的是，由于传入的元素大小是sizeof( B )，显然在pb++的时候移动的距离并非预期的D的长度，也就是说析构函数指针所作用的内存区域必然会出现错误&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;如果非得这么干的话，需要程序员自己解决问题：遍历数组每一个元素，然后 D* d = &amp;amp;((D*)pb)[i]; delete d;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;new运算符的重载&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;例如B* b = new (arena) B();，这里的arena为指定的的内存区域&lt;/li&gt;
&lt;li&gt;实际上编译器做的事情就是将传入的arena参数返回而已&lt;/li&gt;
&lt;li&gt;在编译器其实就相当于B* p = (B*) arena; 不过要做的事情除了决定arena的类型，还得 p-&gt;B::B();&lt;/li&gt;
&lt;li&gt;重复利用一块区域进行构造如何？例如上面操作后再 b = new (arena) B();
&lt;ul&gt;
&lt;li&gt;那么之前new出来的对象不会被析构。&lt;/li&gt;
&lt;li&gt;直接delete b的话，是有问题的，虽然可以调用到析构函数，但b占用的内存区域同样也回收了&lt;/li&gt;
&lt;li&gt;所以需要b-&gt;~b();&lt;/li&gt;
&lt;li&gt;不过标准C++中不需要这么做，编译器的__delete();会进行析构但不释放内存区域&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;C++标准里面规定，利用同一块内存构造新对象的时候，要么是同一类型，要么就是全新的区域，并且大小足够放下这个object&lt;/li&gt;
&lt;li&gt;这么一来，继承的类就不好说了，所以这种new运算符的重载基本是不支持多态的&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;cpp&quot; style=&quot;font-family:monospace;&quot;&gt;B b&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
    b.&lt;span style=&quot;color: #007788;&quot;&gt;ToString&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
    b.~B&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
    &lt;span style=&quot;color: #0000dd;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #000040;&quot;&gt;&amp;amp;&lt;/span&gt;amp&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;b &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; D&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
    b.&lt;span style=&quot;color: #007788;&quot;&gt;ToString&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;哪个类的ToString被调用了？实际上是B的……&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a name=&quot;.E4.B8.B4.E6.97.B6.E5.AF.B9.E8.B1.A1&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;临时对象&lt;/h3&gt;
&lt;p&gt;不太严谨但清晰的定义是：没有别名的局部对象 T a, b; T c = a + b;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不能肯定是否调用了c的拷贝构造函数，并且利用a+b产生的临时对象作为参数&lt;/li&gt;
&lt;li&gt;因为可能产生的NRV优化以及不同的加号运算符重载，可能会直接将a+b的值放入c内&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对于T c = a + b; 和T c; c = a + b;来说可能导致完全不同的结果&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;前者一般都会调用重载的等号运算符，直接传入局部对象引用作为第一个参数&lt;/li&gt;
&lt;li&gt;而后者总是会产生临时对象，调用其等号运算符、再析构&lt;/li&gt;
&lt;li&gt;另外后者需要保证“c是全新的”，而等号运算符又不会调用析构，所以必须保证在赋值前进行析构。&lt;/li&gt;
&lt;li&gt;一般而言前者效率更好&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;关键问题在于临时对象的生存期，即何时调用它的析构函数才合适&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;C++标准规定：对于临时对象的析构应该是完整表达式求值的最后一个步骤&lt;/li&gt;
&lt;li&gt;换句话说在表达式被完全求值之前，所有为此产生的临时对象都不能销毁&lt;/li&gt;
&lt;li&gt;也有例外
&lt;ul&gt;
&lt;li&gt;利用表达式初始化对象 String s = flag ? null : s1 + s2;，也就是说在?后s1+s2产生的临时对象就要析构了。但如果String需要用拷贝构造函数进行初始化的话，必然会位于析构之后，所得到的值也会是错误的。&lt;/li&gt;
&lt;li&gt;利用对象初始化引用时。如果String&amp;amp; s = s1 + s2; 如果引用的临时对象析构了，那引用就没意义了。所以这种情况下，临时对象会在引用失效或者自身失效后进行析构，哪个先到算哪个。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a name=&quot;.E7.AC.AC7.E7.AB.A0_.E7.BB.88.E7.AB.A0&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;第7章 终章&lt;/h2&gt;
&lt;p&gt;&lt;a name=&quot;Template&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Template&lt;/h3&gt;
&lt;p&gt;Template是个非常强大的语法，毋庸置疑。它提供了C++的泛型特性。但由于使用不便，很多人不愿意用。相较于更现代的语言，例如C#和Java，C++利用Template实现的泛型确实不太好理解。 Template的“绑定”会直接替换实际的类型到形参上 对于在Template类里面生命的各种成员而言，编译器在处理Template时候，它们还没有被生成。只有绑定了类型之后才可以使用。例如一个Class B拥有一个enum对象TStatus。但不能直接用B::Status，而只能B&lt;int&gt;::Status。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;所以对于常量之类的，尽量从Template类中提取出来，避免多次拷贝&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对于指针和引用的区别对待&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;B&lt;int&gt;* b = 0;这样做不会产生一个B的实体出来，实际上现在C++标准也禁止编译器这么做&lt;/li&gt;
&lt;li&gt;B&lt;int&gt;&amp;amp; b = 0;这样则会产生一个实体。因为引用不能为空，展开后类似于B&lt;int&gt; tmp( int( 0 ) ); const B&lt;int&gt;&amp;amp; b = tmp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Template的实例化（instantiation）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;指针和引用的例子参见上一条&lt;/li&gt;
&lt;li&gt;并非一次性都实例化完成，用到的才实例化。例如B&lt;int&gt;* b = new B&lt;int&gt;(0); 只会实例化Template本身、构造、析构函数。这是出于效率的考虑。另外new运算符虽然是static的，但它也间接依赖于Template的参数：对象的大小。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Template的错误处理&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一些潜在的错误（非语法错误）：例如给指针赋了错误的值（int* = 1024）、使用类没有实现的运算符。不过编译器都会在实例化Template时候判断出来&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;名称问题&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Template类的定义范围内有一个extern函数，和使用处定义的一个extern函数重名了，那么在Template类成员函数中调用的到底是那个函数？&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;cpp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;//template定义范围内&lt;/span&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;extern&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;double&lt;/span&gt; foo&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;double&lt;/span&gt; aValue &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;template&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;class&lt;/span&gt; T&lt;span style=&quot;color: #000080;&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;class&lt;/span&gt; C1
&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt;
    bar&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt; _v1 &lt;span style=&quot;color: #000080;&quot;&gt;=&lt;/span&gt; foo&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt; _v2 &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt;
    bar2&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt; T aValue &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#123;&lt;/span&gt; _v1 &lt;span style=&quot;color: #000080;&quot;&gt;=&lt;/span&gt; foo&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt; aValue &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#125;&lt;/span&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;:&lt;/span&gt;
    T _v1&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
    &lt;span style=&quot;color: #0000ff;&quot;&gt;int&lt;/span&gt; _v2&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #666666;&quot;&gt;//template使用范围内&lt;/span&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;extern&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;int&lt;/span&gt; foo&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;int&lt;/span&gt; aValue &lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
C1&lt;span style=&quot;color: #000080;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #000080;&quot;&gt;&amp;gt;&lt;/span&gt; c&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;
c.&lt;span style=&quot;color: #007788;&quot;&gt;bar&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008080;&quot;&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;上例中是定义范围内的那个，而不是适用范围内，符合参数类型的那个。&lt;/li&gt;
&lt;li&gt;原则：调用的函数是否和使用的类型相关，不相关就直接使用定义范围的。本例中_v2是很明显的int，不会随着模板参数类型变化而变化，所以直接使用定义范围的。所以如果是调用了bar2()的话，那就会选择使用范围的那个foo()。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;成员函数&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;编译器寻找函数定义：遵循一定的规则，例如一定在头文件对应的同名cpp文件内&lt;/li&gt;
&lt;li&gt;寻找成员函数：Borland生成所有函数；cfront的方法是模拟链接（simulate linkage），只生成需要的&lt;/li&gt;
&lt;li&gt;成员函数实体的唯一性：生成一份，然后在.o中链接&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a name=&quot;.E5.BC.82.E5.B8.B8.E5.A4.84.E7.90.86&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;异常处理&lt;/h3&gt;
&lt;p&gt;中心思想：发生异常的时候查找catch，将局部变量析构掉后让当前函数unwind&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;所以看起来很像的代码可能由于异常处理机制的存在而拥有差别很大的执行期语义&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对于类似互斥锁之类的操作，如果异常发生在lock之后，如何进行unlock？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;提供多个unlock操作，分别放在可能的路径上&lt;/li&gt;
&lt;li&gt;对于更现代的语言来说，都拥有类似finally这样子句来支持异常发生后的对象清理操作&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;再例如一个子类指针指向的数组，分配到某一个元素的基类区域时候发生了一场，那么之前的元素都需要分别调用子类和基类的析构，而发生错误的那个元素只要调用基类的即可，因为子类尚未构造出来。 代码会被划分为多个区段，因为在异常发生前的对象都需要调用析构进行清除，之后的则不用&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;try以外的，没有局部对象的代码段、try以外的，有局部对象的代码段，try代码段&lt;/li&gt;
&lt;li&gt;实现方法：program counter-rage table。记录各个代码段的起始/终止位置&lt;/li&gt;
&lt;li&gt;发生异常的时候，如果当前位置位于try代码段之中，那么就寻找try字句处理&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;异常发生的时候会产生异常对象（exception object），放置在异常栈中&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;throw出去的是地址、type identifier以及可能的异常对象TI&lt;/li&gt;
&lt;li&gt;如果跑出了异常子类而catch的是基类，exObj会被slice off掉非基类的部分&lt;/li&gt;
&lt;li&gt;catch字句结束时，当前的局部exObj就会被销毁。所以如果再一次抛出异常的话，捕获的又是原来的对象了（这节翻译的也太烂了！）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a name=&quot;RTTI&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;RTTI&lt;/h3&gt;
&lt;p&gt;cfront2.0之前，转型运算符*是不能够被重载的&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不过之后就可以了&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;downcast：有用、常用甚至是必要的——但不一定安全的操作 类型安全的downcast操作&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;为了支持安全的downcast需要额外开销：类型信息（TI）和运行时的类型判断（runtime type）&lt;/li&gt;
&lt;li&gt;所以TI的信息就放在vtbl第一个slot位置了&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;类型安全的动态cast操作&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;编译器做了额外的事情帮助程序员处理downcast带来的问题——如果转换失败，返回null而不是指向错误内存的指针&lt;/li&gt;
&lt;li&gt;顺便总结一下三种cast操作的特点（const不用说了）
&lt;ul&gt;
&lt;li&gt;reinterpret_cast。仅指针。编译器解释。不修改格式。不安全。&lt;/li&gt;
&lt;li&gt;static_cast。继承。基本不用于指针，效率不高。不安全。&lt;/li&gt;
&lt;li&gt;dynamic_cast。继承。运行时。指针或引用。安全。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;dynamic_cast的额外开销：执行期通过需要转换的指针获得类型描述
&lt;ul&gt;
&lt;li&gt;(( type_info* )( p-&gt;__vptr[0] ))-&gt;type_descriptor&lt;/li&gt;
&lt;li&gt;拿到之后要交给一个内置的函数判断p指向的类型和这个类型描述是否相符&lt;/li&gt;
&lt;li&gt;本来贝尔实验室的人准备就用type()类似这样的运算符实现dynamic_cast，但C++标委会的人认为这样做和static_cast就没区别了，体现不出来dynamic_cast需要的额外开销&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;重提：引用不是指针&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;和指针不同，引用不能指向到0，所以dynamic_cast失败的时候，只能引发一个异常&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Typeid运算符&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;typeid返回的是一个对于type_info的const reference&lt;/li&gt;
&lt;li&gt;它的==运算符也是被重载的&lt;/li&gt;
&lt;li&gt;type_info的实际结构包括的信息：类名、和其他type_info对象的位置关系、类原名、子类型信息等&lt;/li&gt;
&lt;/ul&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/597572840/siwei/feedsky/s.gif?r=http://wei.si/blog/2011/12/inside-com-study-notes-5-7/&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</content:encoded><wfw:commentRss>http://wei.si/blog/2011/12/inside-com-study-notes-5-7/feed/</wfw:commentRss><slash:comments>2</slash:comments><description>第5章 构造析构和拷贝
虚函数
对于抽象类而言，是否应该自己负责初始化类内的数据成员？（别忘了抽象类也可以有非纯虚函数和数据成员）

一般情况下被认为子类要负责从基类继承来的数据成员的初始化
或者基类必须提供一个显式的构造函数用于自己数据成员的初始化
最好的方法则是将行为和数据分离，提供接口专门用于定义方法


class A_B
&amp;#123;
public:
    virtual ~A_B&amp;#40;&amp;#41; = 0;
    virtual void Say&amp;#40;&amp;#41; const = 0;
    inline char const* GetData&amp;#40;&amp;#41; const &amp;#123; return iData; &amp;#125;
protected:
    A_B&amp;#40; char* aData &amp;#41; : iData&amp;#40; aData &amp;#41; &amp;#123;  &amp;#125;
protected:
    char* iData;
&amp;#125;;
inline A_B::~A_B&amp;#40;&amp;#41; &amp;#123;&amp;#125;
&amp;#160;
class C_D : public [...]&lt;img src=&quot;http://www1.feedsky.com/t1/597572840/siwei/feedsky/s.gif?r=http://wei.si/blog/2011/12/inside-com-study-notes-5-7/&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</description><category>程序</category><category>未分类</category><pubDate>Wed, 14 Dec 2011 22:13:23 +0800</pubDate><author>Si Wei</author><comments>http://wei.si/blog/2011/12/inside-com-study-notes-5-7/#comments</comments><guid isPermaLink="false">http://wei.si/blog/?p=643514</guid><dc:creator>Si Wei</dc:creator><fs:srclink>http://wei.si/blog/2011/12/inside-com-study-notes-5-7/</fs:srclink><fs:srcfeed>http://wei.si/blog/feed/</fs:srcfeed><fs:itemid>feedsky/siwei/~8249691/597572840/1229498</fs:itemid></item><item><title>《涼宮ハルヒの追想》（凉宫春日的追忆）</title><link>http://wei.si/blog/2011/12/suzumiya-haruhi-no-tsuisou/</link><content:encoded>&lt;p&gt;近段时间继续攻略之前没玩过的AVG，花了一周多的通勤时间终于打穿了《涼宮ハルヒの追想》（凉宫春日的追忆）这部大作的汉化版。记得&lt;a href=&quot;http://www.vvpsp.com/pspnews/201103/8167.shtml&quot; target=&quot;_blank&quot;&gt;发布时候就跳票&lt;/a&gt;，好在其游戏质量和时间都足以让人满意。&lt;/p&gt;
&lt;p&gt;故事背景是在《消失》之后，所有事件都是紧随《消失》而发生。故事线则是全新的，并且延续了《消失》中重复某一时间段的方式进行，玩家需要收集各种道具利用在选择肢上，不同的选择会引发不同的分支故事。大概背景就是阿虚某天一醒过来发现又是没有凉宫的世界，当然Happy&lt;br /&gt;
End就是回到原来的世界。同时这个世界还会不停地循环北高祭这两天的故事——如同《凉宫II》那引发争议的“无尽八月”一样的设定，而这次不仅仅是动画折磨人，玩家需要亲身在游戏中体验，真是充满恶意但又让人恨不起来的企划啊。&lt;/p&gt;
&lt;p&gt;另外由于故事设定的场景是北高祭，实际上玩家控制的阿虚在每个时间段的动作——例如前往哪里游玩——也算是另外一种选择，所以这游戏的选择肢系统非常充实，除了刚刚提到的道具选择肢和行动选择肢外，也有下面这种传统意义上的文字类选择：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://wei.si/blog/wp-content/uploads/2011/12/suzumiya_tsuisou_sentaku.gif&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-643556&quot; title=&quot;suzumiya_tsuisou_sentaku&quot; src=&quot;http://wei.si/blog/index.php?feedimage=wp-content/uploads/2011/12/suzumiya_tsuisou_sentaku-300x169.gif&quot; alt=&quot;&quot; width=&quot;300&quot; height=&quot;169&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这几种选择肢中文字类选择中还有很多是“摆设”，也就是选择哪项都会有固定发展。而前两种选择肢比较重要。尤其是道具选择肢，其相关的“时空书签“就是游戏的一大特色。玩家需要在不同的故事线上设定可以返回的书签，以便在拿到需要的道具后快速切换到应用的对话场景中。虽然游戏也提供了SKIP模式可以快速经过已经经历的对话，但合理设定时空书签仍然是节约时间的良策。另外需要注意的是取消掉的时空书签无法重置，也不能随意在当前时间点之前的点上设置。其数量也有限，需要慎重使用。&lt;/p&gt;
&lt;p&gt;不同故事线的发展对应不同的END，虽然有的路线是BAD&lt;br /&gt;
END，但仍然需要走，因为会出现类似A1线需要A2线的道具才能走下去，而A2线又需要B线的道具的情况，甚至有可能B线会利用之前出现过的线路中发现的道具这种让人觉得抓狂的情况。我就遇到过因为游戏中朝比奈学姐（大）的邮件提醒而没有走完一个线结果怎么也进行不下去的情况，所以忠告大家一定要走到死路或者分歧点为止。除了道具之外，玩家还可以收集其他的东西：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;北高祭各个店铺的印章：会以叹号在游览图上进行提示，这个不太好收集，需要非常细心地走完每一条分支。作为速度优先的一周目通关，我大概也就收集到30/120个。惨不忍睹。印章在特典的mini&lt;br /&gt;
game中会有用处，所以还是要多多收集。&lt;/li&gt;
&lt;li&gt;END：没记错的话应该是21个，其中大家喜闻乐见的应该是只有一个（不肯定），其余的都是各种结局。我现在进度是16/21。这也证明有些路线没有走到。&lt;/li&gt;
&lt;li&gt;CG和BGM：基本上进度和END是同步的。分别是90个和20个左右。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;游戏最设定有朝比奈学姐（大）利用邮件提醒协助玩家上手，路线也比较少。随着故事发展，人物关系和手中的道具开始变化和增多，后期的故事线可能会变成这样：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://wei.si/blog/wp-content/uploads/2011/12/suzumiya_tsuisou_bunki.gif&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-643557&quot; title=&quot;suzumiya_tsuisou_bunki&quot; src=&quot;http://wei.si/blog/index.php?feedimage=wp-content/uploads/2011/12/suzumiya_tsuisou_bunki-300x169.gif&quot; alt=&quot;&quot; width=&quot;300&quot; height=&quot;169&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;所以如何分配有限的书签使用，是不走冤枉路的关键。我的策略一般是开头的分歧点设定一个，之后见到有道具出现前的分歧点设定，拿到道具后可以快速返回，而实在走不通了之后也可以回到最初的时间点。&lt;/p&gt;
&lt;p&gt;游戏的画面无需多说，京ANI的作品作画上一向安定且让人放心，唯一让人觉得有些别扭的是开头这个立绘，可能是穿上了光阳园学院的制服，让人感觉团长侧脸有些奇怪。但整体上无论是人物立绘、道具、背景都是相当相当细致，&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://wei.si/blog/wp-content/uploads/2011/12/suzumiya_tsuisou_tate.gif&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-643558&quot; title=&quot;suzumiya_tsuisou_tate&quot; src=&quot;http://wei.si/blog/index.php?feedimage=wp-content/uploads/2011/12/suzumiya_tsuisou_tate-300x169.gif&quot; alt=&quot;&quot; width=&quot;300&quot; height=&quot;169&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;除了立绘之外游戏中还穿插有3D场景，有些是为了表现北高祭中其他摊位的活动情况，有些则是使用了2D效果渲染的3D人物模型，在关键对话（需要进行选择对话内容以推动故事发展）以及关键场景（增强表现力）中会出现：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://wei.si/blog/wp-content/uploads/2011/12/suzumiya_tsuisou_3d.gif&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-643559&quot; title=&quot;suzumiya_tsuisou_3d&quot; src=&quot;http://wei.si/blog/index.php?feedimage=wp-content/uploads/2011/12/suzumiya_tsuisou_3d-300x169.gif&quot; alt=&quot;&quot; width=&quot;300&quot; height=&quot;169&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;《追忆》的可视元素和音乐非常出色，完美地保持了《凉宫》系列一贯的风格（OP就是动画第一季经典的“冒险冒险”，并且在内容精细程度上提升（估计是为了PS3版本吧，PSP沾光）。&lt;/p&gt;
&lt;p&gt;除此之外，我觉得更难得的是，游戏在故事上也下足了功夫，请回顾一下上面那张时间线（又差点打成世界线）的图，我要说负责剧本和脚本的STAFF们真是辛苦了，要在“重复48小时”这种设定上进行故事的编写，既要体现出统一性又不能搞出太多的重复元素，实在是够难。另外正传中出现的其他人物，例如鹤屋学姐、电研社长、国木田和谷口等都悉数出场，如何安插这些人物的活动也值得考虑。综合考虑，我觉得这是毫无疑问的良心作。&lt;/p&gt;
&lt;p&gt;一周目通关已经比较满足，因为没有收集全成就/CG的习惯。所以接下来可能搁置《追忆》，玩一部老作品《Never7》。&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/597572841/siwei/feedsky/s.gif?r=http://wei.si/blog/2011/12/suzumiya-haruhi-no-tsuisou/&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</content:encoded><wfw:commentRss>http://wei.si/blog/2011/12/suzumiya-haruhi-no-tsuisou/feed/</wfw:commentRss><slash:comments>0</slash:comments><description>近段时间继续攻略之前没玩过的AVG，花了一周多的通勤时间终于打穿了《涼宮ハルヒの追想》（凉宫春日的追忆）这部大作的汉化版。记得发布时候就跳票，好在其游戏质量和时间都足以让人满意。
故事背景是在《消失》之后，所有事件都是紧随《消失》而发生。故事线则是全新的，并且延续了《消失》中重复某一时间段的方式进行，玩家需要收集各种道具利用在选择肢上，不同的选择会引发不同的分支故事。大概背景就是阿虚某天一醒过来发现又是没有凉宫的世界，当然Happy
End就是回到原来的世界。同时这个世界还会不停地循环北高祭这两天的故事——如同《凉宫II》那引发争议的“无尽八月”一样的设定，而这次不仅仅是动画折磨人，玩家需要亲身在游戏中体验，真是充满恶意但又让人恨不起来的企划啊。
另外由于故事设定的场景是北高祭，实际上玩家控制的阿虚在每个时间段的动作——例如前往哪里游玩——也算是另外一种选择，所以这游戏的选择肢系统非常充实，除了刚刚提到的道具选择肢和行动选择肢外，也有下面这种传统意义上的文字类选择：

这几种选择肢中文字类选择中还有很多是“摆设”，也就是选择哪项都会有固定发展。而前两种选择肢比较重要。尤其是道具选择肢，其相关的“时空书签“就是游戏的一大特色。玩家需要在不同的故事线上设定可以返回的书签，以便在拿到需要的道具后快速切换到应用的对话场景中。虽然游戏也提供了SKIP模式可以快速经过已经经历的对话，但合理设定时空书签仍然是节约时间的良策。另外需要注意的是取消掉的时空书签无法重置，也不能随意在当前时间点之前的点上设置。其数量也有限，需要慎重使用。
不同故事线的发展对应不同的END，虽然有的路线是BAD
END，但仍然需要走，因为会出现类似A1线需要A2线的道具才能走下去，而A2线又需要B线的道具的情况，甚至有可能B线会利用之前出现过的线路中发现的道具这种让人觉得抓狂的情况。我就遇到过因为游戏中朝比奈学姐（大）的邮件提醒而没有走完一个线结果怎么也进行不下去的情况，所以忠告大家一定要走到死路或者分歧点为止。除了道具之外，玩家还可以收集其他的东西：

北高祭各个店铺的印章：会以叹号在游览图上进行提示，这个不太好收集，需要非常细心地走完每一条分支。作为速度优先的一周目通关，我大概也就收集到30/120个。惨不忍睹。印章在特典的mini
game中会有用处，所以还是要多多收集。
END：没记错的话应该是21个，其中大家喜闻乐见的应该是只有一个（不肯定），其余的都是各种结局。我现在进度是16/21。这也证明有些路线没有走到。
CG和BGM：基本上进度和END是同步的。分别是90个和20个左右。

游戏最设定有朝比奈学姐（大）利用邮件提醒协助玩家上手，路线也比较少。随着故事发展，人物关系和手中的道具开始变化和增多，后期的故事线可能会变成这样：

所以如何分配有限的书签使用，是不走冤枉路的关键。我的策略一般是开头的分歧点设定一个，之后见到有道具出现前的分歧点设定，拿到道具后可以快速返回，而实在走不通了之后也可以回到最初的时间点。
游戏的画面无需多说，京ANI的作品作画上一向安定且让人放心，唯一让人觉得有些别扭的是开头这个立绘，可能是穿上了光阳园学院的制服，让人感觉团长侧脸有些奇怪。但整体上无论是人物立绘、道具、背景都是相当相当细致，

除了立绘之外游戏中还穿插有3D场景，有些是为了表现北高祭中其他摊位的活动情况，有些则是使用了2D效果渲染的3D人物模型，在关键对话（需要进行选择对话内容以推动故事发展）以及关键场景（增强表现力）中会出现：

《追忆》的可视元素和音乐非常出色，完美地保持了《凉宫》系列一贯的风格（OP就是动画第一季经典的“冒险冒险”，并且在内容精细程度上提升（估计是为了PS3版本吧，PSP沾光）。
除此之外，我觉得更难得的是，游戏在故事上也下足了功夫，请回顾一下上面那张时间线（又差点打成世界线）的图，我要说负责剧本和脚本的STAFF们真是辛苦了，要在“重复48小时”这种设定上进行故事的编写，既要体现出统一性又不能搞出太多的重复元素，实在是够难。另外正传中出现的其他人物，例如鹤屋学姐、电研社长、国木田和谷口等都悉数出场，如何安插这些人物的活动也值得考虑。综合考虑，我觉得这是毫无疑问的良心作。
一周目通关已经比较满足，因为没有收集全成就/CG的习惯。所以接下来可能搁置《追忆》，玩一部老作品《Never7》。&lt;img src=&quot;http://www1.feedsky.com/t1/597572841/siwei/feedsky/s.gif?r=http://wei.si/blog/2011/12/suzumiya-haruhi-no-tsuisou/&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</description><category>动漫</category><category>游戏</category><pubDate>Mon, 12 Dec 2011 20:27:07 +0800</pubDate><author>Si Wei</author><comments>http://wei.si/blog/2011/12/suzumiya-haruhi-no-tsuisou/#comments</comments><guid isPermaLink="false">http://wei.si/blog/?p=643560</guid><dc:creator>Si Wei</dc:creator><fs:srclink>http://wei.si/blog/2011/12/suzumiya-haruhi-no-tsuisou/</fs:srclink><fs:srcfeed>http://wei.si/blog/feed/</fs:srcfeed><fs:itemid>feedsky/siwei/~8249691/597572841/1229498</fs:itemid></item><item><title>《涼宮ハルヒの追想》（凉宫春日的追忆）</title><link>http://wei.si/blog/2011/12/suzumiya-haruhi-no-tsuisou/</link><content:encoded>&lt;p&gt;近段时间继续攻略之前没玩过的AVG，花了一周多的通勤时间终于打穿了《涼宮ハルヒの追想》（凉宫春日的追忆）这部大作的汉化版。记得&lt;a href=&quot;http://www.vvpsp.com/pspnews/201103/8167.shtml&quot; target=&quot;_blank&quot;&gt;发布时候就跳票&lt;/a&gt;，好在其游戏质量和时间都足以让人满意。&lt;/p&gt;
&lt;p&gt;故事背景是在《消失》之后，所有事件都是紧随《消失》而发生。故事线则是全新的，并且延续了《消失》中重复某一时间段的方式进行，玩家需要收集各种道具利用在选择肢上，不同的选择会引发不同的分支故事。大概背景就是阿虚某天一醒过来发现又是没有凉宫的世界，当然Happy End就是回到原来的世界。同时这个世界还会不停地循环北高祭这两天的故事——如同《凉宫II》那引发争议的“无尽八月”一样的设定，而这次不仅仅是动画折磨人，玩家需要亲身在游戏中体验，真是充满恶意但又让人恨不起来的企划啊。&lt;/p&gt;
&lt;p&gt;另外由于故事设定的场景是北高祭，实际上玩家控制的阿虚在每个时间段的动作——例如前往哪里游玩——也算是另外一种选择，所以这游戏的选择肢系统非常充实，除了刚刚提到的道具选择肢和行动选择肢外，也有下面这种传统意义上的文字类选择：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://wei.si/blog/wp-content/uploads/2011/12/suzumiya_tsuisou_sentaku.gif&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-643557&quot; title=&quot;suzumiya_tsuisou_sentaku&quot; src=&quot;http://wei.si/blog/index.php?feedimage=wp-content/uploads/2011/12/suzumiya_tsuisou_sentaku-300x169.gif&quot; alt=&quot;&quot; width=&quot;300&quot; height=&quot;169&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这几种选择肢中文字类选择中还有很多是“摆设”，也就是选择哪项都会有固定发展。而前两种选择肢比较重要。尤其是道具选择肢，其相关的“时空书签“就是游戏的一大特色。玩家需要在不同的故事线上设定可以返回的书签，以便在拿到需要的道具后快速切换到应用的对话场景中。虽然游戏也提供了SKIP模式可以快速经过已经经历的对话，但合理设定时空书签仍然是节约时间的良策。另外需要注意的是取消掉的时空书签无法重置，也不能随意在当前时间点之前的点上设置。其数量也有限，需要慎重使用。&lt;/p&gt;
&lt;p&gt;不同故事线的发展对应不同的END，虽然有的路线是BAD END，但仍然需要走，因为会出现类似A1线需要A2线的道具才能走下去，而A2线又需要B线的道具的情况，甚至有可能B线会利用之前出现过的线路中发现的道具这种让人觉得抓狂的情况。我就遇到过因为游戏中朝比奈学姐（大）的邮件提醒而没有走完一个线结果怎么也进行不下去的情况，所以忠告大家一定要走到死路或者分歧点为止。除了道具之外，玩家还可以收集其他的东西：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;北高祭各个店铺的印章：会以叹号在游览图上进行提示，这个不太好收集，需要非常细心地走完每一条分支。作为速度优先的一周目通关，我大概也就收集到30/120个。惨不忍睹。印章在特典的mini game中会有用处，所以还是要多多收集。&lt;/li&gt;
&lt;li&gt;END：没记错的话应该是21个，其中大家喜闻乐见的应该是只有一个（不肯定），其余的都是各种结局。我现在进度是16/21。这也证明有些路线没有走到。&lt;/li&gt;
&lt;li&gt;CG和BGM：基本上进度和END是同步的。分别是90个和20个左右。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;游戏最设定有朝比奈学姐（大）利用邮件提醒协助玩家上手，路线也比较少。随着故事发展，人物关系和手中的道具开始变化和增多，后期的故事线可能会变成这样：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://wei.si/blog/wp-content/uploads/2011/12/suzumiya_tsuisou_bunki.gif&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-643559&quot; title=&quot;suzumiya_tsuisou_bunki&quot; src=&quot;http://wei.si/blog/index.php?feedimage=wp-content/uploads/2011/12/suzumiya_tsuisou_bunki-300x169.gif&quot; alt=&quot;&quot; width=&quot;300&quot; height=&quot;169&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;所以如何分配有限的书签使用，是不走冤枉路的关键。我的策略一般是开头的分歧点设定一个，之后见到有道具出现前的分歧点设定，拿到道具后可以快速返回，而实在走不通了之后也可以回到最初的时间点。&lt;/p&gt;
&lt;p&gt;游戏的画面无需多说，京ANI的作品作画上一向安定且让人放心，唯一让人觉得有些别扭的是开头这个立绘，可能是穿上了光阳园学院的制服，让人感觉团长侧脸有些奇怪。但整体上无论是人物立绘、道具、背景都是相当相当细致，&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://wei.si/blog/wp-content/uploads/2011/12/suzumiya_tsuisou_tate.gif&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-643560&quot; title=&quot;suzumiya_tsuisou_tate&quot; src=&quot;http://wei.si/blog/index.php?feedimage=wp-content/uploads/2011/12/suzumiya_tsuisou_tate-300x169.gif&quot; alt=&quot;&quot; width=&quot;300&quot; height=&quot;169&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;除了立绘之外游戏中还穿插有3D场景，有些是为了表现北高祭中其他摊位的活动情况，有些则是使用了2D效果渲染的3D人物模型，在关键对话（需要进行选择对话内容以推动故事发展）以及关键场景（增强表现力）中会出现：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://wei.si/blog/wp-content/uploads/2011/12/suzumiya_tsuisou_3d.gif&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-643561&quot; title=&quot;suzumiya_tsuisou_3d&quot; src=&quot;http://wei.si/blog/index.php?feedimage=wp-content/uploads/2011/12/suzumiya_tsuisou_3d-300x169.gif&quot; alt=&quot;&quot; width=&quot;300&quot; height=&quot;169&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;《追忆》的可视元素和音乐非常出色，完美地保持了《凉宫》系列一贯的风格（OP就是动画第一季经典的“冒险冒险”，并且在内容精细程度上提升（估计是为了PS3版本吧，PSP沾光）。&lt;/p&gt;
&lt;p&gt;除此之外，我觉得更难得的是，游戏在故事上也下足了功夫，请回顾一下上面那张时间线（又差点打成世界线）的图，我要说负责剧本和脚本的STAFF们真是辛苦了，要在“重复48小时”这种设定上进行故事的编写，既要体现出统一性又不能搞出太多的重复元素，实在是够难。另外正传中出现的其他人物，例如鹤屋学姐、电研社长、国木田和谷口等都悉数出场，如何安插这些人物的活动也值得考虑。综合考虑，我觉得这是毫无疑问的良心作。&lt;/p&gt;
&lt;p&gt;一周目通关已经比较满足，因为没有收集全成就/CG的习惯。所以接下来可能搁置《追忆》，玩一部老作品《Never7》。&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/586155192/siwei/feedsky/s.gif?r=http://wei.si/blog/2011/12/suzumiya-haruhi-no-tsuisou/&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</content:encoded><wfw:commentRss>http://wei.si/blog/2011/12/suzumiya-haruhi-no-tsuisou/feed/</wfw:commentRss><slash:comments>0</slash:comments><description>近段时间继续攻略之前没玩过的AVG，花了一周多的通勤时间终于打穿了《涼宮ハルヒの追想》（凉宫春日的追忆）这部大作的汉化版。记得发布时候就跳票，好在其游戏质量和时间都足以让人满意。
故事背景是在《消失》之后，所有事件都是紧随《消失》而发生。故事线则是全新的，并且延续了《消失》中重复某一时间段的方式进行，玩家需要收集各种道具利用在选择肢上，不同的选择会引发不同的分支故事。大概背景就是阿虚某天一醒过来发现又是没有凉宫的世界，当然Happy End就是回到原来的世界。同时这个世界还会不停地循环北高祭这两天的故事——如同《凉宫II》那引发争议的“无尽八月”一样的设定，而这次不仅仅是动画折磨人，玩家需要亲身在游戏中体验，真是充满恶意但又让人恨不起来的企划啊。
另外由于故事设定的场景是北高祭，实际上玩家控制的阿虚在每个时间段的动作——例如前往哪里游玩——也算是另外一种选择，所以这游戏的选择肢系统非常充实，除了刚刚提到的道具选择肢和行动选择肢外，也有下面这种传统意义上的文字类选择：

这几种选择肢中文字类选择中还有很多是“摆设”，也就是选择哪项都会有固定发展。而前两种选择肢比较重要。尤其是道具选择肢，其相关的“时空书签“就是游戏的一大特色。玩家需要在不同的故事线上设定可以返回的书签，以便在拿到需要的道具后快速切换到应用的对话场景中。虽然游戏也提供了SKIP模式可以快速经过已经经历的对话，但合理设定时空书签仍然是节约时间的良策。另外需要注意的是取消掉的时空书签无法重置，也不能随意在当前时间点之前的点上设置。其数量也有限，需要慎重使用。
不同故事线的发展对应不同的END，虽然有的路线是BAD END，但仍然需要走，因为会出现类似A1线需要A2线的道具才能走下去，而A2线又需要B线的道具的情况，甚至有可能B线会利用之前出现过的线路中发现的道具这种让人觉得抓狂的情况。我就遇到过因为游戏中朝比奈学姐（大）的邮件提醒而没有走完一个线结果怎么也进行不下去的情况，所以忠告大家一定要走到死路或者分歧点为止。除了道具之外，玩家还可以收集其他的东西：

北高祭各个店铺的印章：会以叹号在游览图上进行提示，这个不太好收集，需要非常细心地走完每一条分支。作为速度优先的一周目通关，我大概也就收集到30/120个。惨不忍睹。印章在特典的mini game中会有用处，所以还是要多多收集。
END：没记错的话应该是21个，其中大家喜闻乐见的应该是只有一个（不肯定），其余的都是各种结局。我现在进度是16/21。这也证明有些路线没有走到。
CG和BGM：基本上进度和END是同步的。分别是90个和20个左右。

游戏最设定有朝比奈学姐（大）利用邮件提醒协助玩家上手，路线也比较少。随着故事发展，人物关系和手中的道具开始变化和增多，后期的故事线可能会变成这样：

所以如何分配有限的书签使用，是不走冤枉路的关键。我的策略一般是开头的分歧点设定一个，之后见到有道具出现前的分歧点设定，拿到道具后可以快速返回，而实在走不通了之后也可以回到最初的时间点。
游戏的画面无需多说，京ANI的作品作画上一向安定且让人放心，唯一让人觉得有些别扭的是开头这个立绘，可能是穿上了光阳园学院的制服，让人感觉团长侧脸有些奇怪。但整体上无论是人物立绘、道具、背景都是相当相当细致，

除了立绘之外游戏中还穿插有3D场景，有些是为了表现北高祭中其他摊位的活动情况，有些则是使用了2D效果渲染的3D人物模型，在关键对话（需要进行选择对话内容以推动故事发展）以及关键场景（增强表现力）中会出现：

《追忆》的可视元素和音乐非常出色，完美地保持了《凉宫》系列一贯的风格（OP就是动画第一季经典的“冒险冒险”，并且在内容精细程度上提升（估计是为了PS3版本吧，PSP沾光）。
除此之外，我觉得更难得的是，游戏在故事上也下足了功夫，请回顾一下上面那张时间线（又差点打成世界线）的图，我要说负责剧本和脚本的STAFF们真是辛苦了，要在“重复48小时”这种设定上进行故事的编写，既要体现出统一性又不能搞出太多的重复元素，实在是够难。另外正传中出现的其他人物，例如鹤屋学姐、电研社长、国木田和谷口等都悉数出场，如何安插这些人物的活动也值得考虑。综合考虑，我觉得这是毫无疑问的良心作。
一周目通关已经比较满足，因为没有收集全成就/CG的习惯。所以接下来可能搁置《追忆》，玩一部老作品《Never7》。&lt;img src=&quot;http://www1.feedsky.com/t1/586155192/siwei/feedsky/s.gif?r=http://wei.si/blog/2011/12/suzumiya-haruhi-no-tsuisou/&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</description><category>游戏</category><pubDate>Sun, 11 Dec 2011 18:53:58 +0800</pubDate><author>Si Wei</author><comments>http://wei.si/blog/2011/12/suzumiya-haruhi-no-tsuisou/#comments</comments><guid isPermaLink="false">http://wei.si/blog/?p=643556</guid><dc:creator>Si Wei</dc:creator><fs:srclink>http://wei.si/blog/2011/12/suzumiya-haruhi-no-tsuisou/</fs:srclink><fs:srcfeed>http://wei.si/blog/feed/</fs:srcfeed><fs:itemid>feedsky/siwei/~8249691/586155192/1229498</fs:itemid></item><item><title>Yeah！</title><link>http://wei.si/blog/2011/12/yeah/</link><content:encoded>&lt;p&gt;昨天看到这里时候我忍不住记录下来了：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://wei.si/blog/wp-content/uploads/2011/12/cba_beijing_win_81.jpg&quot;&gt;&lt;img class=&quot;aligncenter size-medium wp-image-643552&quot; title=&quot;cba_beijing_win_81&quot; src=&quot;http://wei.si/blog/index.php?feedimage=wp-content/uploads/2011/12/cba_beijing_win_81-300x225.jpg&quot; alt=&quot;&quot; width=&quot;300&quot; height=&quot;225&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;作为一个从小学开始看了首钢篮球15年的老球迷，从没像昨晚那样感觉心情舒畅。以前别说打八一能赢40分，基本就是少输当赢。在八一主场更是从没赢过，不管换了几个球馆，八一主场对首钢队来说如同黑洞，球员来来去去换了几十个，鹿指导也从球员打到教练二次上任，依然没赢过。但今年马指导降临之后首钢队明显精气神不同，加上两个强力新人，连三吉这种之前一直被说软的球员都可以持续发挥（参见近几场统计）。&lt;/p&gt;
&lt;p&gt;另外不得不提一下李学林，根据&lt;a href=&quot;http://cba.hoopchina.com/players/lixuelin6.html&quot; target=&quot;_blank&quot;&gt;统计&lt;/a&gt;，他前8场总共助攻30个（场均3.75）；失误是多少？说出来吓人，只有4个，而且是4场各1个，其余四场0。7.5的助攻失误比太可怕了。全华班阵容中他的作用从昨天第一节就可以看出来，而可以上外援的时候，无论是双控卫还是学林+莫大爷的组合都是非常可怕。&lt;/p&gt;
&lt;p&gt;明天首钢和浙江的比赛有得看。&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/597572842/siwei/feedsky/s.gif?r=http://wei.si/blog/2011/12/yeah/&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</content:encoded><wfw:commentRss>http://wei.si/blog/2011/12/yeah/feed/</wfw:commentRss><slash:comments>0</slash:comments><description>昨天看到这里时候我忍不住记录下来了：

作为一个从小学开始看了首钢篮球15年的老球迷，从没像昨晚那样感觉心情舒畅。以前别说打八一能赢40分，基本就是少输当赢。在八一主场更是从没赢过，不管换了几个球馆，八一主场对首钢队来说如同黑洞，球员来来去去换了几十个，鹿指导也从球员打到教练二次上任，依然没赢过。但今年马指导降临之后首钢队明显精气神不同，加上两个强力新人，连三吉这种之前一直被说软的球员都可以持续发挥（参见近几场统计）。
另外不得不提一下李学林，根据统计，他前8场总共助攻30个（场均3.75）；失误是多少？说出来吓人，只有4个，而且是4场各1个，其余四场0。7.5的助攻失误比太可怕了。全华班阵容中他的作用从昨天第一节就可以看出来，而可以上外援的时候，无论是双控卫还是学林+莫大爷的组合都是非常可怕。
明天首钢和浙江的比赛有得看。&lt;img src=&quot;http://www1.feedsky.com/t1/597572842/siwei/feedsky/s.gif?r=http://wei.si/blog/2011/12/yeah/&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</description><category>体育</category><pubDate>Fri, 09 Dec 2011 00:01:27 +0800</pubDate><author>Si Wei</author><comments>http://wei.si/blog/2011/12/yeah/#comments</comments><guid isPermaLink="false">http://wei.si/blog/?p=643551</guid><dc:creator>Si Wei</dc:creator><fs:srclink>http://wei.si/blog/2011/12/yeah/</fs:srclink><fs:srcfeed>http://wei.si/blog/feed/</fs:srcfeed><fs:itemid>feedsky/siwei/~8249691/597572842/1229498</fs:itemid></item><item><title>打自己脸——有关.net对象分配</title><link>http://wei.si/blog/2011/12/about-net-object-allocation/</link><content:encoded>&lt;p&gt;之前发过的那篇&lt;a href=&quot;http://wei.si/blog/2011/12/dotnet-gc-and-gc-knowledge-study-notes/&quot; target=&quot;_blank&quot;&gt;.NET的GC机制和GC知识学习&lt;/a&gt;里面有一选项为：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;A. 值类型的对象会被分配到Stack上，而引用类型的对象会被分配到Large Object Heap上。&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;今天在写前一篇Blog时候，发现这句话其实大错特错，虽然这个选项本身就是故意加入了错误，作为选择题答案出现，但此错非彼错。还好题目没有正式使用，不然会被人打脸打得啪啪响。在尚未被人打脸之前还是先自打比较好。先看前半句：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;值类型的对象会被分配到Stack上&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;拿值类型中最常被提到用来和引用类型相比较的Struct来说，它一定分配到Stack上吗？当然不是。这一点题目已经涉及到了，就是大于85k的对象会分配到LOH上。但忽略的一点是一般尺寸的值类型对象也有可能分配到Heap上：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;类成员变量，就算是值类型也是在Heap上分配；&lt;/li&gt;
&lt;li&gt;局部值类型变量，涉及到和闭包相关的特性时。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;第一条就不说了。第二条例如下面这个例子，i和j都是局部值类型变量，他们都在Stack上吗？&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;csharp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;private&lt;/span&gt; &lt;span style=&quot;color: #0600FF;&quot;&gt;void&lt;/span&gt; Form1_Load&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;object&lt;/span&gt; sender, EventArgs e &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span style=&quot;color: #FF0000;&quot;&gt;int&lt;/span&gt; j &lt;span style=&quot;color: #008000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt;
    &lt;span style=&quot;color: #FF0000;&quot;&gt;int&lt;/span&gt; i &lt;span style=&quot;color: #008000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt;
    Func foo &lt;span style=&quot;color: #008000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;=&amp;amp;&lt;/span&gt;gt&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;
        &lt;span style=&quot;color: #0600FF;&quot;&gt;return&lt;/span&gt; i&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt;
    &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div&gt;当然是否定的，拿出il代码看一下就明了：从声明上来看，j的确是在Stack上没错，但i却是依附在一个编译器自动生成的类&amp;lt;&amp;gt;c__DisplayClass3上面；进行赋值时候i用的是stfld而不是stloc。这也就是说对于闭包涉及到的局部变量而言，CLR会将其依附到一个自动生成的类上进行存取操作，那么它自然就不分配到Stack上了。&lt;/div&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;il&quot; style=&quot;font-family:monospace;&quot;&gt;.method private hidebysig instance void  Form1_Load(object sender,
class [mscorlib]System.EventArgs e) cil managed
{
// 代码大小       31 (0x1f)
.maxstack  3
.locals init (&amp;lt;span style=&amp;quot;color: #ff0000;&amp;quot;&amp;gt;[0] int32 j&amp;lt;/span&amp;gt;,
[1] class [System.Core]System.Func`1 foo,
&amp;lt;span style=&amp;quot;color: #ff0000;&amp;quot;&amp;gt;[2] class WindowsFormsApplication1.Form1/'&amp;amp;lt;&amp;amp;gt;c__DisplayClass3' 'CS$&amp;amp;lt;&amp;amp;gt;8__locals4'&amp;lt;/span&amp;gt;)
IL_0000:  newobj     instance void WindowsFormsApplication1.Form1/'&amp;amp;lt;&amp;amp;gt;c__DisplayClass3'::.ctor()
IL_0005:  stloc.2
IL_0006:  nop
IL_0007:  ldc.i4.0
IL_0008:  &amp;lt;span style=&amp;quot;color: #ff0000;&amp;quot;&amp;gt;stloc.0&amp;lt;/span&amp;gt;
IL_0009:  ldloc.2
IL_000a:  ldc.i4.0
IL_000b:  &amp;lt;span style=&amp;quot;color: #ff0000;&amp;quot;&amp;gt;stfld      int32 WindowsFormsApplication1.Form1/'&amp;amp;lt;&amp;amp;gt;c__DisplayClass3'::i&amp;lt;/span&amp;gt;
IL_0010:  ldloc.2
IL_0011:  ldftn      instance int32 WindowsFormsApplication1.Form1/'&amp;amp;lt;&amp;amp;gt;c__DisplayClass3'::'
b__2'()
IL_0017:  newobj     instance void class [System.Core]System.Func`1::.ctor(object,
native int)
IL_001c:  stloc.1
IL_001d:  nop
IL_001e:  ret
} // end of method Form1::Form1_Load&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;另外漏了一点，在&lt;a href=&quot;http://kb.cnblogs.com/a/1663655/&quot; target=&quot;_blank&quot;&gt;更正：值类型并不总是分配在栈上&lt;/a&gt;一文中提到，还有一种会被分配到Heap上的值类型：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数组内的值类型对象，会被一同分配到Heap上。&lt;/li&gt;
&lt;/ul&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/597572843/siwei/feedsky/s.gif?r=http://wei.si/blog/2011/12/about-net-object-allocation/&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</content:encoded><wfw:commentRss>http://wei.si/blog/2011/12/about-net-object-allocation/feed/</wfw:commentRss><slash:comments>0</slash:comments><description>之前发过的那篇.NET的GC机制和GC知识学习里面有一选项为：
A. 值类型的对象会被分配到Stack上，而引用类型的对象会被分配到Large Object Heap上。
今天在写前一篇Blog时候，发现这句话其实大错特错，虽然这个选项本身就是故意加入了错误，作为选择题答案出现，但此错非彼错。还好题目没有正式使用，不然会被人打脸打得啪啪响。在尚未被人打脸之前还是先自打比较好。先看前半句：
值类型的对象会被分配到Stack上
拿值类型中最常被提到用来和引用类型相比较的Struct来说，它一定分配到Stack上吗？当然不是。这一点题目已经涉及到了，就是大于85k的对象会分配到LOH上。但忽略的一点是一般尺寸的值类型对象也有可能分配到Heap上：

类成员变量，就算是值类型也是在Heap上分配；
局部值类型变量，涉及到和闭包相关的特性时。

第一条就不说了。第二条例如下面这个例子，i和j都是局部值类型变量，他们都在Stack上吗？

private void Form1_Load&amp;#40; object sender, EventArgs e &amp;#41; &amp;#123;
    int j = 0;
    int i = 0;
    Func foo = &amp;#40;&amp;#41; =&amp;#38;gt; &amp;#123;
        return i;
    &amp;#125;;
&amp;#125;

当然是否定的，拿出il代码看一下就明了：从声明上来看，j的确是在Stack上没错，但i却是依附在一个编译器自动生成的类&amp;#60;&amp;#62;c__DisplayClass3上面；进行赋值时候i用的是stfld而不是stloc。这也就是说对于闭包涉及到的局部变量而言，CLR会将其依附到一个自动生成的类上进行存取操作，那么它自然就不分配到Stack上了。

.method private hidebysig instance void  Form1_Load(object sender,
class [...]&lt;img src=&quot;http://www1.feedsky.com/t1/597572843/siwei/feedsky/s.gif?r=http://wei.si/blog/2011/12/about-net-object-allocation/&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</description><category>程序</category><pubDate>Mon, 05 Dec 2011 16:10:13 +0800</pubDate><author>Si Wei</author><comments>http://wei.si/blog/2011/12/about-net-object-allocation/#comments</comments><guid isPermaLink="false">http://wei.si/blog/?p=643544</guid><dc:creator>Si Wei</dc:creator><fs:srclink>http://wei.si/blog/2011/12/about-net-object-allocation/</fs:srclink><fs:srcfeed>http://wei.si/blog/feed/</fs:srcfeed><fs:itemid>feedsky/siwei/~8249691/597572843/1229498</fs:itemid></item><item><title>一些关于闭包的废话</title><link>http://wei.si/blog/2011/12/craps-on-closure/</link><content:encoded>&lt;p&gt;继函数形参传值传指针、GC机制的Blog后，貌似这又是说烂的问题？没办法，最近在回顾各种知识，发现有联系的就拿出来写一写，省得日后发霉。如果你现在对闭包还不是很了解，可以阅读一下&lt;a title=&quot;http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html&quot; rel=&quot;nofollow&quot; href=&quot;http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html&quot; target=&quot;_blank&quot;&gt;学习Javascript闭包（Closure）&lt;/a&gt;、&lt;a title=&quot;http://ghsky.com/2010/10/deep-into-javascript-closure-part-one.html&quot; rel=&quot;nofollow&quot; href=&quot;http://ghsky.com/2010/10/deep-into-javascript-closure-part-one.html&quot; target=&quot;_blank&quot;&gt;深入理解JavaScript闭包（1）&lt;/a&gt;和&lt;a title=&quot;http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html&quot; rel=&quot;nofollow&quot; href=&quot;http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html&quot; target=&quot;_blank&quot;&gt;理解 JavaScript 闭包&lt;/a&gt;三篇文章。难度依次上升。&lt;/p&gt;
&lt;h2&gt;JavaScript的闭包&lt;/h2&gt;
&lt;p&gt;闭包的概念已经比科学发展观都深入人心了，简单说它就是“具有独立作用域并且可以引用外层作用域的对象”。例如C#中的匿名函数和Lambda表达式就是基于的闭包概念，其他的高级语言，类似Java、JavaScript和Python等也都有闭包的应用。当然也不要忘了JavaScript的内存泄露主因之一也是闭包，所以先看JS好了。&lt;/p&gt;
&lt;p&gt;还是先从代码入手，下面两段代码是从阮一峰老师的那篇闭包讲解中摘取的最后习题，那么现在提问，两段代码分别alert什么内容？&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;javascript&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; bar &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&amp;quot;Global&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
　　&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; object1 &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;
　　　　bar &lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&amp;quot;local&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;
　　　　foo &lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;
　　　　　　&lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;
　　　　　　　　&lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;this&lt;/span&gt;.&lt;span style=&quot;color: #660066;&quot;&gt;bar&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
　　　　　　&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
　　　　&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;
　　&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
　　&lt;span style=&quot;color: #000066;&quot;&gt;alert&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;object1.&lt;span style=&quot;color: #660066;&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
&amp;nbsp;
&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;//我是分隔线&lt;/span&gt;
&amp;nbsp;
　　&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; object2 &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;
　　　　bar &lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&amp;quot;local&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;
　　　　foo &lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;
          &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; that &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
　　　　　　&lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;
　　　　　　　　&lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;return&lt;/span&gt; that.&lt;span style=&quot;color: #660066;&quot;&gt;bar&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
　　　　　　&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
　　　　&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;
　　&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
　　&lt;span style=&quot;color: #000066;&quot;&gt;alert&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;object2.&lt;span style=&quot;color: #660066;&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;span id=&quot;more-643538&quot;&gt;&lt;/span&gt;答案分别是&amp;#8221;Global&amp;#8221;和&amp;#8221;Local&amp;#8221;。alert中的参数是一个调用链，直接用第一次返回的对象（函数对象）执行，所以会有()()这种奇怪的语法。对于两次的调用，我们可以拆解为：&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;javascript&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; calleeA1 &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; object1.&lt;span style=&quot;color: #660066;&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; calleeA2 &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; calleeA1&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;//object2类似，不写了。&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;既然.运算符后面的内容相同，那么必然是.之前的this指代不同。根据JavaScript中this关键字的特性可知，它表示&lt;strong&gt;调用者&lt;/strong&gt;，也就是方法运行时候的上下文。对于object1而言，第一次.foo()之后，函数foo()所在的上下文和this指代就是window了，那么返回的bar就是全局的；反之object2中that = this则是将object2的this交给function使用。所以返回的是object.bar。简而言之就是闭包所在的区域中值并不是一次绑定，而是随着执行变化的，所以上文中this的指代会有所不同。&lt;/p&gt;
&lt;p&gt;这个例子可以用更有趣的方式改编[4]：&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;javascript&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;function&lt;/span&gt; object1&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;this&lt;/span&gt;.&lt;span style=&quot;color: #660066;&quot;&gt;foo&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;a&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;
        &lt;span style=&quot;color: #000066;&quot;&gt;alert&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;a&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
        &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;this&lt;/span&gt;.&lt;span style=&quot;color: #660066;&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
    &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;new&lt;/span&gt; object1&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span style=&quot;color: #660066;&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
&amp;nbsp;
&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;//我是分隔线&lt;/span&gt;
&amp;nbsp;
&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;function&lt;/span&gt; object2&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; that &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
    &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;this&lt;/span&gt;.&lt;span style=&quot;color: #660066;&quot;&gt;foo&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;a&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;
        &lt;span style=&quot;color: #000066;&quot;&gt;alert&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;a&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
        &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;return&lt;/span&gt; that.&lt;span style=&quot;color: #660066;&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
    &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;new&lt;/span&gt; object2&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span style=&quot;color: #660066;&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;虽然形式不同，但原因是一样的：如果没有动态绑定this，那么它就是window的指代。所以在()()后window.foo = undefine，再()就是失败了。&lt;/p&gt;
&lt;h2&gt;闭包陷阱&lt;/h2&gt;
&lt;p&gt;仍然是先看代码，运行一下两段代码，看看区别：&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;javascript&quot; style=&quot;font-family:monospace;&quot;&gt;arr &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;new&lt;/span&gt; Array&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; i &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt; i &lt;span style=&quot;color: #339933;&quot;&gt;&amp;amp;&lt;/span&gt;lt&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #CC0000;&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;++&lt;/span&gt;i &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;
    arr.&lt;span style=&quot;color: #660066;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;return&lt;/span&gt; i&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;
&lt;span style=&quot;color: #000066;&quot;&gt;alert&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt; arr&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;+&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&amp;quot;,&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;+&lt;/span&gt; arr&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;9&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
&amp;nbsp;
&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;//我是分隔线&lt;/span&gt;
&amp;nbsp;
arr2 &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;new&lt;/span&gt; Array&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; i &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt; i &lt;span style=&quot;color: #339933;&quot;&gt;&amp;amp;&lt;/span&gt;lt&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #CC0000;&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;++&lt;/span&gt;i &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;
    arr2.&lt;span style=&quot;color: #660066;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;return&lt;/span&gt; i&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;
&lt;span style=&quot;color: #000066;&quot;&gt;alert&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt; arr2&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;+&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&amp;quot;,&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;+&lt;/span&gt; arr2&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;9&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;分别输出了&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre&gt;0,9
10,10&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;闭包造成的晚绑定（lazy binding）让局部作用域获取到的变量是&lt;strong&gt;运行时&lt;/strong&gt;才确定的，所以把function对象加入Array之后，运行时拿到了一直保存着的局部变量i（别忘了闭包产生了变量引用，i不会被析构掉），这个i对于任何arr2中的对象都是等价的。&lt;/p&gt;
&lt;h2&gt;Java和.Net的闭包&lt;/h2&gt;
&lt;p&gt;目前Android平台的Java上（或者是所有版本的Java上？），让人很恼火的就是写下面代码的时候：&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;java&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;int&lt;/span&gt; i &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #cc66cc;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt; i &lt;span style=&quot;color: #339933;&quot;&gt;&amp;amp;&lt;/span&gt;lt&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt; length&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt; i&lt;span style=&quot;color: #339933;&quot;&gt;++&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span style=&quot;color: #003399;&quot;&gt;Button&lt;/span&gt; button &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: #003399;&quot;&gt;Button&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt; getContext&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
    setButtonListener&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt; button, i &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
    button.&lt;span style=&quot;color: #006633;&quot;&gt;setOnClickListener&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;new&lt;/span&gt; OnClickListener&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;
        @Override
        &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;void&lt;/span&gt; onClick&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #003399;&quot;&gt;View&lt;/span&gt; v &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;
            setFocused&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt; i &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
        &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;
    &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;/blockquote&gt;
&lt;p&gt;就会被提示说“i不是final的 blah blah blah”，但很明显在一个循环中我们不可能将自增量设定为final，所以就不得不写成：&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;java&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;int&lt;/span&gt; i &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #cc66cc;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt; i &lt;span style=&quot;color: #339933;&quot;&gt;&amp;amp;&lt;/span&gt;lt&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt; length&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt; i&lt;span style=&quot;color: #339933;&quot;&gt;++&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;
            &lt;span style=&quot;color: #003399;&quot;&gt;Button&lt;/span&gt; button &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: #003399;&quot;&gt;Button&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt; getContext&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
            setButtonListener&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt; button, i &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
        &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//绑定函数&lt;/span&gt;
    &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;private&lt;/span&gt; &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;void&lt;/span&gt; setButtonListener&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #003399;&quot;&gt;Button&lt;/span&gt; aButton, &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;final&lt;/span&gt; &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;int&lt;/span&gt; aIndex &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;
        aButton.&lt;span style=&quot;color: #006633;&quot;&gt;setOnClickListener&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;new&lt;/span&gt; OnClickListener&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;
            @Override
            &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;void&lt;/span&gt; onClick&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #003399;&quot;&gt;View&lt;/span&gt; v &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;
                setFocused&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt; aIndex &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
            &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;
        &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
    &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;也就是说，Java支持匿名类，但如果使用的话，它的参数，包括使用的局部变量，都必须是final的。那么为什么如此设计[2]？在[2]中提到：&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre&gt;The methods in an anonymous class don't really have access to local variables and method parameters.
Rather, when an object of the anonymous class is instantiated,
copies of the final local variables and method parameters referred to by the object's methods are stored as instance variables in the object.
The methods in the object of the anonymous class really access those hidden instance variables.
匿名类中的方法并不能访问局部变量和方法参数。在匿名类的对象实例化时，
final修饰的局部变量和方法参数的副本会被对象方法引用，并且作为实例变量存储在对象中。
匿名类对象的方法实际上访问的是这些隐藏的实例变量。&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;验证这一点可以查看编译后的*$1.class文件，其中匿名类对象使用的各种变量、参数都变成了private final的，在编译期就决定了取值。但这只是另一种表现方式，至于真正的原因恐怕只有Java语言的设计者和开发者才知道了，简单考虑一下不外乎：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;维护对象的可用性、一致性（final），避免出现意外问题&lt;/li&gt;
&lt;li&gt;就是不支持闭包，各位感觉如何？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;没错，Java 在JDK 7之前实际上不支持闭包特性。Java.net之前做过一个调查[3]，在开发者感兴趣但Java不支持的特性中，闭包的票数遥遥领先：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Closures 47% (856 votes)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a title=&quot;http://www.java.net/pub/pq/117&quot; rel=&quot;nofollow&quot; href=&quot;http://www.java.net/pub/pq/117&quot; target=&quot;_blank&quot;&gt;另外一个询问是否希望在JDK 7中见到闭包的调查&lt;/a&gt;中，支持的也占到了四成。另外比较有趣的是“不知道什么是闭包”的票数比“不希望支持闭包”的还多。我们虽然可以用某种方式&lt;a title=&quot;http://liuxuan.info/blog/2011/02/10/simulate-closure-in-java/&quot; rel=&quot;nofollow&quot; href=&quot;http://liuxuan.info/blog/2011/02/10/simulate-closure-in-java/&quot; target=&quot;_blank&quot;&gt;在Java中进行闭包的模拟&lt;/a&gt;，但说白了还是必须进行静态绑定的匿名函数，就像上面那段代码中演示的一样。其实对于Java中闭包特性是否应该支持的争论由来已久，比如[3]这么个平和的问题竟然引发了论战，另外还有&lt;a title=&quot;http://www.ibm.com/developerworks/cn/java/j-jtp04247.html&quot; rel=&quot;nofollow&quot; href=&quot;http://www.ibm.com/developerworks/cn/java/j-jtp04247.html&quot; target=&quot;_blank&quot;&gt;Java 理论与实践: 闭包之争&lt;/a&gt;这样历史悠久的帖子（4年前）从各种专业角度讨论闭包的优劣。希望增加闭包特性的人奇怪这个特性强大好用居家旅行必备，这个问题简直不值得讨论；而反对增加的人主要是觉得Lambda表达式会给“纯洁的”Java增加许多函数式编程特性，语法变得奇形怪状。Sun易手之后，去年Oracle终于扭扭捏捏地在Java 7里面支持了“简单闭包”，也就是用“#”声明的Lambda表达式：&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;java&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;int&lt;/span&gt; i &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; #&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #cc66cc;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;//也可以写成：&lt;/span&gt;
#int&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; foo &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; #&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #cc66cc;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;int&lt;/span&gt; i &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; foo.&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;不少Java开发者看到后都这样：( ´ﾟдﾟ)(ﾟдﾟ｀ )。先不说那个莫名其妙的#，调用方法时候的“.”也显得多余。&lt;/p&gt;
&lt;p&gt;对比一下C#中的Lambda表达式：&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;csharp&quot; style=&quot;font-family:monospace;&quot;&gt;Func&lt;span style=&quot;color: #008000;&quot;&gt;&amp;amp;&lt;/span&gt;lt&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt;int&lt;span style=&quot;color: #008000;&quot;&gt;&amp;amp;&lt;/span&gt;gt&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt; foo &lt;span style=&quot;color: #008000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;=&amp;amp;&lt;/span&gt;gt&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #FF0000;&quot;&gt;int&lt;/span&gt; i &lt;span style=&quot;color: #008000;&quot;&gt;=&lt;/span&gt; foo&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #008080; font-style: italic;&quot;&gt;//也可以写成&lt;/span&gt;
&lt;span style=&quot;color: #FF0000;&quot;&gt;delegate&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;int&lt;/span&gt; bar&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt;
bar b &lt;span style=&quot;color: #008000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;=&amp;amp;&lt;/span&gt;gt&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #FF0000;&quot;&gt;int&lt;/span&gt; i &lt;span style=&quot;color: #008000;&quot;&gt;=&lt;/span&gt; b&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;C#中的Func类实际上是一种特殊的delegate，这样无论是匿名方法、delegate、匿名函数、Lambda表达式还是event，都用一根线串起来了。从各种意义上C#都是由Java而生、借鉴了很多优点的语言，但这次Java的“简单闭包”特性更像是匆匆上马，未经过任何雕琢和详细论证。其被批丑陋不仅仅是#这个奇怪的语法，更在于不完整的特性支持。于是婊Java时候就又多了一道利器，连博客园大牛老赵（Jeffrey Zhao）在系列文章&lt;a title=&quot;http://blog.zhaojie.me/2010/04/why-java-sucks-and-csharp-rocks-1-thoughts-and-goals.html&quot; rel=&quot;nofollow&quot; href=&quot;http://blog.zhaojie.me/2010/04/why-java-sucks-and-csharp-rocks-1-thoughts-and-goals.html&quot; target=&quot;_blank&quot;&gt;Why Java Sucks and C# Rock&lt;/a&gt;也提到了相关内容。&lt;/p&gt;
&lt;p&gt;老实说我不太喜欢过多的匿名对象出现在代码中，虽然.net和VS强大到连这样的代码运行、调试都没问题，但我实在担心有后来人看完代码后我自己的人身安全。&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;csharp&quot; style=&quot;font-family:monospace;&quot;&gt;&lt;span style=&quot;color: #0600FF;&quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;int&lt;/span&gt; i &lt;span style=&quot;color: #008000;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #FF0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt; i &lt;span style=&quot;color: #008000;&quot;&gt;&amp;amp;&lt;/span&gt;lt&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt; _imgs.&lt;span style=&quot;color: #0000FF;&quot;&gt;Length&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt; i&lt;span style=&quot;color: #008000;&quot;&gt;++&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;
    ImageItem item &lt;span style=&quot;color: #008000;&quot;&gt;=&lt;/span&gt; _imgs&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#91;&lt;/span&gt;i&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt;
    item.&lt;span style=&quot;color: #0000FF;&quot;&gt;Image&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;=&lt;/span&gt; ImageBank.&lt;span style=&quot;color: #0000FF;&quot;&gt;Instance&lt;/span&gt;.&lt;span style=&quot;color: #0000FF;&quot;&gt;Get&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt; item.&lt;span style=&quot;color: #0000FF;&quot;&gt;ImageUrl&lt;/span&gt;, &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt; source &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;=&amp;amp;&lt;/span&gt;gt&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;
        Deployment.&lt;span style=&quot;color: #0000FF;&quot;&gt;Current&lt;/span&gt;.&lt;span style=&quot;color: #0000FF;&quot;&gt;Dispatcher&lt;/span&gt;.&lt;span style=&quot;color: #0000FF;&quot;&gt;BeginInvoke&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;=&amp;amp;&lt;/span&gt;gt&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#123;&lt;/span&gt;
            item.&lt;span style=&quot;color: #0000FF;&quot;&gt;Image&lt;/span&gt; &lt;span style=&quot;color: #008000;&quot;&gt;=&lt;/span&gt; source&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt;
        &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt;
    &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2&gt;延伸阅读&lt;/h2&gt;
&lt;p&gt;刚好看到Jeffrey Zhao时隔一年又开始轮Java了：&lt;a title=&quot;http://blog.zhaojie.me/2011/11/sun-whitepaper-about-microsoft-delegates.html&quot; rel=&quot;nofollow&quot; href=&quot;http://blog.zhaojie.me/2011/11/sun-whitepaper-about-microsoft-delegates.html&quot; target=&quot;_blank&quot;&gt;挖坟鞭尸：当年Sun公司的白皮书《About Microsoft “Delegates”》&lt;/a&gt;。评论比文章有趣，而且信息量大多了。&lt;/p&gt;
&lt;p&gt;一片翻译文，从代码层次对比两种语言的闭包机制：&lt;a href=&quot;http://www.cnblogs.com/Klesh/archive/2008/05/15/The-Beauty-of-Closures.html&quot; target=&quot;_blank&quot;&gt;C#和Java的闭包－Jon谈《The Beauty of Closures》&lt;/a&gt;。&lt;/p&gt;
&lt;h2&gt;参考资料&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a title=&quot;http://liuxuan.info/blog/2011/02/10/simulate-closure-in-java/&quot; rel=&quot;nofollow&quot; href=&quot;http://liuxuan.info/blog/2011/02/10/simulate-closure-in-java/&quot; target=&quot;_blank&quot;&gt;闭包及其在Java中的模拟实现&lt;/a&gt;, liuxuan&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;http://www.developer.com/java/other/article.php/3300881/The-Essence-of-OOP-using-Java-Anonymous-Classes.htm&quot; rel=&quot;nofollow&quot; href=&quot;http://www.developer.com/java/other/article.php/3300881/The-Essence-of-OOP-using-Java-Anonymous-Classes.htm&quot; target=&quot;_blank&quot;&gt;The Essence of OOP using Java, Anonymous Classes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;http://www.java.net/pub/pq/240&quot; rel=&quot;nofollow&quot; href=&quot;http://www.java.net/pub/pq/240&quot; target=&quot;_blank&quot;&gt;Which of these excluded-from-Java-7 features were you most interested in?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;http://topic.csdn.net/u/20111202/10/9307c181-65f2-4fce-828e-5ad30d3e769b.html&quot; rel=&quot;nofollow&quot; href=&quot;http://topic.csdn.net/u/20111202/10/9307c181-65f2-4fce-828e-5ad30d3e769b.html&quot; target=&quot;_blank&quot;&gt;超级BT的JS写法。&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;http://developer.51cto.com/art/201001/179418.htm&quot; rel=&quot;nofollow&quot; href=&quot;http://developer.51cto.com/art/201001/179418.htm&quot; target=&quot;_blank&quot;&gt;Java 7的第一类函数：学习闭包的使用&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/597572844/siwei/feedsky/s.gif?r=http://wei.si/blog/2011/12/craps-on-closure/&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</content:encoded><wfw:commentRss>http://wei.si/blog/2011/12/craps-on-closure/feed/</wfw:commentRss><slash:comments>0</slash:comments><description>继函数形参传值传指针、GC机制的Blog后，貌似这又是说烂的问题？没办法，最近在回顾各种知识，发现有联系的就拿出来写一写，省得日后发霉。如果你现在对闭包还不是很了解，可以阅读一下学习Javascript闭包（Closure）、深入理解JavaScript闭包（1）和理解 JavaScript 闭包三篇文章。难度依次上升。
JavaScript的闭包
闭包的概念已经比科学发展观都深入人心了，简单说它就是“具有独立作用域并且可以引用外层作用域的对象”。例如C#中的匿名函数和Lambda表达式就是基于的闭包概念，其他的高级语言，类似Java、JavaScript和Python等也都有闭包的应用。当然也不要忘了JavaScript的内存泄露主因之一也是闭包，所以先看JS好了。
还是先从代码入手，下面两段代码是从阮一峰老师的那篇闭包讲解中摘取的最后习题，那么现在提问，两段代码分别alert什么内容？

var bar = &amp;#34;Global&amp;#34;;
　　var object1 = &amp;#123;
　　　　bar : &amp;#34;local&amp;#34;,
　　　　foo : function&amp;#40;&amp;#41;&amp;#123;
　　　　　　return function&amp;#40;&amp;#41;&amp;#123;
　　　　　　　　return this.bar;
　　　　　　&amp;#125;;
　　　　&amp;#125;
　　&amp;#125;;
　　alert&amp;#40;object1.foo&amp;#40;&amp;#41;&amp;#40;&amp;#41;&amp;#41;;
&amp;#160;
//我是分隔线
&amp;#160;
　　var object2 = &amp;#123;
　　　　bar : &amp;#34;local&amp;#34;,
　　　　foo : function&amp;#40;&amp;#41;&amp;#123;
          var that = this;
　　　　　　return function&amp;#40;&amp;#41;&amp;#123;
　　　　　　　　return that.bar;
　　　　　　&amp;#125;;
　　　　&amp;#125;
　　&amp;#125;;
　　alert&amp;#40;object2.foo&amp;#40;&amp;#41;&amp;#40;&amp;#41;&amp;#41;;

答案分别是&amp;#8221;Global&amp;#8221;和&amp;#8221;Local&amp;#8221;。alert中的参数是一个调用链，直接用第一次返回的对象（函数对象）执行，所以会有()()这种奇怪的语法。对于两次的调用，我们可以拆解为：

var calleeA1 = object1.foo&amp;#40;&amp;#41;;
var calleeA2 = calleeA1&amp;#40;&amp;#41;;
//object2类似，不写了。

既然.运算符后面的内容相同，那么必然是.之前的this指代不同。根据JavaScript中this关键字的特性可知，它表示调用者，也就是方法运行时候的上下文。对于object1而言，第一次.foo()之后，函数foo()所在的上下文和this指代就是window了，那么返回的bar就是全局的；反之object2中that = this则是将object2的this交给function使用。所以返回的是object.bar。简而言之就是闭包所在的区域中值并不是一次绑定，而是随着执行变化的，所以上文中this的指代会有所不同。
这个例子可以用更有趣的方式改编[4]：

function object1&amp;#40;&amp;#41;&amp;#123;
    this.foo = function&amp;#40;a&amp;#41;&amp;#123;
    [...]&lt;img src=&quot;http://www1.feedsky.com/t1/597572844/siwei/feedsky/s.gif?r=http://wei.si/blog/2011/12/craps-on-closure/&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</description><category>程序</category><pubDate>Mon, 05 Dec 2011 13:09:22 +0800</pubDate><author>Si Wei</author><comments>http://wei.si/blog/2011/12/craps-on-closure/#comments</comments><guid isPermaLink="false">http://wei.si/blog/?p=643538</guid><dc:creator>Si Wei</dc:creator><fs:srclink>http://wei.si/blog/2011/12/craps-on-closure/</fs:srclink><fs:srcfeed>http://wei.si/blog/feed/</fs:srcfeed><fs:itemid>feedsky/siwei/~8249691/597572844/1229498</fs:itemid></item><item><title>.NET的GC机制和GC知识学习</title><link>http://wei.si/blog/2011/12/dotnet-gc-and-gc-knowledge-study-notes/</link><content:encoded>&lt;p&gt;在刚刚完成的一套.net笔试题卷子中，出了这样一道题：&lt;/p&gt;
&lt;p&gt;面有关垃圾收集（GC）机制的说法中正确的是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A. 值类型的对象会被分配到Stack上，而引用类型的对象会被分配到Large Object Heap上。&lt;/li&gt;
&lt;li&gt;B. 使用try/catch/finally在效率上并不优于使用using的方式。&lt;/li&gt;
&lt;li&gt;C. 可以实现自定义引用类型的Finalize方法，但它不能被重载。&lt;/li&gt;
&lt;li&gt;D. GC的垃圾回收动作可以在代码中手动调用。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;答案是BCD，A中错误在于引用对象会被默认分配到GC Heap的SOH（Small Object Heap）上，超过85KB对象会被分配到LOH。至于85K这个Magic Number的由来，应该是编写.Net框架的工程师们经过平时各种使用场景和优化推算出来的，我们不必多费心研究。&lt;/p&gt;
&lt;p&gt;那么GC Heap为什么要分两类呢？这要从SOH和LOH不同的垃圾清理机制说起。&lt;/p&gt;
&lt;h2&gt;.Net的GC机制&lt;/h2&gt;
&lt;h3&gt;GC Heap&lt;/h3&gt;
&lt;p&gt;对于LOH来说，清理垃圾的过程等于“回收+归并”，即不仅要清理掉内存空间，还要将尚存的对象向着一个方向移动直到和之前的对象紧紧贴在一起[1][3]。如下所示，SOH上有四个对象：&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre&gt;[obj1][    obj2     ][  obj3  ][obj4]
↑
0代指针（p0）&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;经过一次清理后，obj2和obj4没了，留下来的都是1代对象，并将0代指针移动到内存低位的第一个空闲空间处：&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre&gt;[obj1][  obj3  ][obj5]
↑               ↑
p1              p0&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;2代对象的生成类似，这样的移动保证不会产生大量的内存碎片，最大程度提高了内存使用效率。&lt;/p&gt;
&lt;p&gt;可惜对于大对象来说，移动的成本过高，所以会优先采用查找可用剩余碎片空间的方式，将可以容纳新对象的空间重复利用。类似上面的内存情况在0代清理、新分配了obj5后会变成：&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre&gt;[obj1][obj5]         [  obj3  ]&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;obj5和obj3之间的内存如果小于85K就很可惜，因为再也利用不起来了。&lt;/p&gt;
&lt;p&gt;不过需要注意的是，虽然大对象&lt;strong&gt;目前&lt;/strong&gt;不会被归并处理，但不保证未来的CLR版本会不会实现一个LOH也进行存留对象移动的版本，所以希望保持现在这种行为的话，需要在变量前加fixed关键字进行标识。&lt;/p&gt;
&lt;h3&gt;分代处理&lt;/h3&gt;
&lt;p&gt;上文提到的0、1代是.Net中采用的分代垃圾回收机制的体现。目前.Net的GC中支持的代数为2（GC.MaxGeneration），一般来说，可以将0-2这三代对象视作：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;0代，大多数对象，GC进行回收时候都会被处理掉&lt;/li&gt;
&lt;li&gt;2代，少数常驻内存的对象，例如asp.net和整个网站生存期等同的一些全局对象&lt;/li&gt;
&lt;li&gt;1代，介于0代和2代之间的一个灰色地带。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在GC动作的时候，0代会首先会被回收，如果需要的内存空间不够用再依次处理1和2代对象。&lt;/p&gt;
&lt;p&gt;对于程序中的引用对象，可以通过GC.GetGeneration()获取它的代数，这个方法还有一个重载版本支持WeakReference。&lt;/p&gt;
&lt;p&gt;&lt;span id=&quot;more-643525&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;其他细节&lt;/h3&gt;
&lt;p&gt;对于.Net平台上托管（Managed）类型的语言来说，一切对象的创建都是程序员负责，但回收就不用操心了。CLR中的托管堆上存放的都是引用类型的对象，在没有垃圾回收机制的语言和框架中，这些对象必须自己处理，例如利用C++中的delete语句。&lt;/p&gt;
&lt;p&gt;托管堆上的存放已生成的引用对象的具体数据，同时维护一个指针指向最后生成对象的末端，供下一次对象创建的时候确定位置和判断剩余空间是否满足新对象的大小。在GC每一次执行清理的时候，首先会假设所有托管堆上的对象都是可回收的。当然要是这样就坏了因为毕竟有些对象在使用，所以.Net采用了根集合（Root Collection）的方式进行处理，根集合中的包括的对象有静态对象、全局对象、CPU寄存器存储的对象以及其他强引用对象。。&lt;/p&gt;
&lt;p&gt;GC机制判断那些对象可用（usable），在.Net中这个术语叫做可达（reachable），即循着跟对象我们能找到某个对象，换句话说它被根对象或者其他动态生成的对象持有一个引用。这样查找过一遍之后，所有“不可达”的对象就是清理的目标。之后的事情在上面提到过，即它们将会被清理+归并，以压缩内存空间。综合这些操作考虑，.Net中GC的效率较高的原因在于：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对托管堆上所有对象遍历进行可达性标记的过程，其复杂度固定为O(n)，但由于是分代进行，所以尽量减少了检查及清理的数量&lt;/li&gt;
&lt;li&gt;每一次回收后，对象所在内存区域都是连续的&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;另外，GC上进行各种操作的部分应该是多线程进行的，为了保证对象安全性，在GC运行的时候.Net会直接Stop the World进行操作，一般来说是中断，但也有用到Richter大神那篇文章里面提到的其他机制，例如Hijacking和Safe Points等等。&lt;/p&gt;
&lt;h3&gt;Finalize和析构&lt;/h3&gt;
&lt;p&gt;Finalize方法在CLR中的实现形式如同C++中的析构函数，即“~”加上类名。但请注意，托管对象是&lt;strong&gt;不能被析构&lt;/strong&gt;的，它们只能进行Finalize然后等待GC的清理操作。这个方法虽然用起来像析构，但绝对不是析构。.Net的各种大牛都会教导我们：尽量不要覆盖Finalize方法。原因无外乎两点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;空间损耗。Finalize覆盖后，对象会被提升代数，获得更久的生存期，但真的需要这么做吗？这就是问题所在。另外如果引用了其他没有覆盖Finalize方法的对象后，还会造成关联对象的延迟清理。&lt;/li&gt;
&lt;li&gt;时间损耗。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以如果真的覆盖这个方法的话，就让它执行时间尽量短吧。另外编译器也不会自动帮你在子类中补完或自动调用基类中覆盖了的Finalize，一切都要靠自己了。&lt;/p&gt;
&lt;p&gt;这么一看Finalize似乎百害而无一利了？并非如此，如果你的托管对象调用了&lt;strong&gt;非托管对象&lt;/strong&gt;的话，.Net不会好心将非托管对象所占用的各种资源一并帮你释放掉，所以你需要自己实现托管对象的Finalize，在这个会在某一时刻调用的方法内进行资源释放。但老实说，如果你的类对于资源敏感，又要提供给别人使用，光留下一个清理资源的Finalize方法也让别人没法下嘴啊（Finalize是不可以被手动调用的），所以一定要覆盖或者提供一个Close类型的方法，可以让使用者手动释放资源。比如.Net框架内的各种Stream类，都实现了IDisposable接口。&lt;/p&gt;
&lt;p&gt;那么在CLR内部Finalize的实现又如何呢？对于自己实现了Finalize方法的类来说，除了GC Heap之外，它们还有另外一个去处，叫做Freachable Queue。这个队列配合另外的Finalization Queue（真正的死亡队列……）可以巧妙地实现托管/非托管资源都能完全释放的目的。在GC执行回收动作时，和刚才说的一样，所有不可达的对象都&lt;strong&gt;将&lt;/strong&gt;会被清理掉。其中CLR会判断出实现Finalize的类，将其放入Freachable Queue，由另外一个线程遍历其中的对象，一一执行其资源释放的方法。不过进入了Freachable Queue后，对象就变成根对象了，也就是说如果还没来得及执行Finalize也没有问题，下次的垃圾清理对于根对象是不会直接干掉的。&lt;/p&gt;
&lt;p&gt;需要注意的是，一般来说对象变成不可达对象后，只会进入到Freachable Queue一次，所以Finalize也只会跑一次。这么看的话在这个方法中执行任何造成强引用的语句是非常不安全的，因为被引用的对象可能无法被释放。为此GC.ReRegisterForFinalize方法可以让对象重新进入Freachable Queue，解决这类问题。但老实说我之前从未覆盖过Finalize，也没有用过GC.ReRegisterForFinalize，所以也提供不了具体的使用场景。&lt;/p&gt;
&lt;p&gt;刚刚提到Finalize不可以手动调用，那么最后说说Finalize的（被）调用时机[2]：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;0代对象Heap满了，这也是最常见的场景&lt;/li&gt;
&lt;li&gt;手动调用了GC.Collect()&lt;/li&gt;
&lt;li&gt;Windows内存不足。CLR接到了CreateMemoryResourceNotification或者QueueMemoryResourceNotification机制带来的低内存通知&lt;/li&gt;
&lt;li&gt;CLR卸载一个应用程序域（AppDomain）&lt;/li&gt;
&lt;li&gt;CLR整体Shutting Down时候。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;GC实现方式&lt;/h2&gt;
&lt;p&gt;上面是对.Net内GC机制一些细节的总结，这一节则是学习有关GC知识的笔记。之前面试中问过一些有关GC的问题，例如“C/C++上为什么不自带GC机制？”“如果希望实现一个的话采用什么思路？”“是否了解.Net或者Java平台上的GC机制”等等，但很可惜，大家都跟我一样不太了解这块的知识。对于C/C++程序员来说不了解GC机制正常，但应该具有设计一个自动化资源管理框架（不一定是GC）的能力；而靠托管平台、拥有GC的平台吃饭的程序员应该了解一些底层的知识。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;分代&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;分代GC应该是最新的、得到系统论证的GC方式，在资源有限的情况下其效率普遍比其他方法要高。具体细节请参考上一节。&lt;/p&gt;
&lt;h3&gt;引用计数&lt;/h3&gt;
&lt;p&gt;引用计数（RC）是智能指针的实现基础之一，也是最经典的自动管理内存方式。引用计数的实现简单，但问题在于，进行计数的话我们只知道对象被引用了多少次，但不能知道&lt;strong&gt;谁引用了这个对象&lt;/strong&gt;。所以就造成了最经典的问题，RC中出现循环引用导致内存泄露。目前一些脚本语言采用RC方式进行自动化资源管理，例如Python和Javascript[5]，前者的实现用RC确保对象的快速清理，但也用到了标记清理循环引用的对象；后者则是完全基于RC的管理机制，结果我们也看到了，在一些实现有问题的引擎上，Javascript可能会出现内存泄漏，而其最经典的特性之一——闭包——也有可能造成内存泄露。&lt;/p&gt;
&lt;p&gt;Objective C语言和iOS开发框架内，似乎也用的是RC方式进行内存管理，自己实现的类要确保引用数和引用释放数量的对等。当然可能这么说不准确，毕竟只写过几百行代码，没有实际应用。&lt;/p&gt;
&lt;h3&gt;标记（染色）&lt;/h3&gt;
&lt;p&gt;标记也是现代GC机制中必不可少的一环。例如Lua语言的GC实现就充分利用标记，……以下总结自参考资料里面云风大牛的系列文章[4]，其中也有具体的代码层次Lua GC实现机制：&lt;/p&gt;
&lt;pre&gt;它采用三色方式（黑白灰）分别对各个对象进行染色，白色表示无引用，黑色表示正在用，而灰色是未检查的对象。
当然其中还会掺杂强弱引用的概念，导致实际的“颜色”远大于3种。
Lua中实际的清理也是分布进行的，先标记再下手清除。&lt;/pre&gt;
&lt;p&gt;这一点上和.Net上的GC对于每一代对象判断是否可达再清除别无二致。一般来说这两个步骤的复杂度都为O(n)，应该算是比较安定的操作。&lt;/p&gt;
&lt;h3&gt;拷贝&lt;/h3&gt;
&lt;p&gt;拷贝的内存清理机制是将内存分为两块，其中一块永远保持空闲。一次清理后会将存活对象顺序拷贝到空闲区域。好处在于省下了内存压缩的时间，但空间消耗的代价太大了。&lt;/p&gt;
&lt;h2&gt;参考资料&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a title=&quot;http://msdn.microsoft.com/zh-cn/magazine/bb985011(en-us).aspx&quot; rel=&quot;nofollow&quot; href=&quot;http://msdn.microsoft.com/zh-cn/magazine/bb985011(en-us).aspx&quot; target=&quot;_blank&quot;&gt;Garbage Collectionâ&amp;#8221;Part 2: Automatic Memory Management in the Microsoft .NET Framework&lt;/a&gt;, Jeffrey Richter&lt;/li&gt;
&lt;li&gt;CLR via C#, Jeffrey Richter&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;http://www.cnblogs.com/yukaizhao/archive/2011/11/23/dot_net_GC_1.html&quot; rel=&quot;nofollow&quot; href=&quot;http://www.cnblogs.com/yukaizhao/archive/2011/11/23/dot_net_GC_1.html&quot; target=&quot;_blank&quot;&gt;.Net 垃圾回收机制原理（一）&lt;/a&gt;, yukaizhao&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;http://blog.codingnow.com/2008/06/gc.html&quot; rel=&quot;nofollow&quot; href=&quot;http://blog.codingnow.com/2008/06/gc.html&quot; target=&quot;_blank&quot;&gt;引用计数与垃圾收集之比较&lt;/a&gt;, 云风&lt;/li&gt;
&lt;li&gt;Javascript: The Definitive Guide, 4th Edition&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;http://stackoverflow.com/questions/21934/why-java-and-python-garbage-collection-methods-are-different&quot; rel=&quot;nofollow&quot; href=&quot;http://stackoverflow.com/questions/21934/why-java-and-python-garbage-collection-methods-are-different&quot; target=&quot;_blank&quot;&gt;Why Java and Python garbage collection methods are different?&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/597572845/siwei/feedsky/s.gif?r=http://wei.si/blog/2011/12/dotnet-gc-and-gc-knowledge-study-notes/&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</content:encoded><wfw:commentRss>http://wei.si/blog/2011/12/dotnet-gc-and-gc-knowledge-study-notes/feed/</wfw:commentRss><slash:comments>0</slash:comments><description>在刚刚完成的一套.net笔试题卷子中，出了这样一道题：
面有关垃圾收集（GC）机制的说法中正确的是：

A. 值类型的对象会被分配到Stack上，而引用类型的对象会被分配到Large Object Heap上。
B. 使用try/catch/finally在效率上并不优于使用using的方式。
C. 可以实现自定义引用类型的Finalize方法，但它不能被重载。
D. GC的垃圾回收动作可以在代码中手动调用。

答案是BCD，A中错误在于引用对象会被默认分配到GC Heap的SOH（Small Object Heap）上，超过85KB对象会被分配到LOH。至于85K这个Magic Number的由来，应该是编写.Net框架的工程师们经过平时各种使用场景和优化推算出来的，我们不必多费心研究。
那么GC Heap为什么要分两类呢？这要从SOH和LOH不同的垃圾清理机制说起。
.Net的GC机制
GC Heap
对于LOH来说，清理垃圾的过程等于“回收+归并”，即不仅要清理掉内存空间，还要将尚存的对象向着一个方向移动直到和之前的对象紧紧贴在一起[1][3]。如下所示，SOH上有四个对象：

[obj1][    obj2     ][  obj3  ][obj4]
↑
0代指针（p0）

经过一次清理后，obj2和obj4没了，留下来的都是1代对象，并将0代指针移动到内存低位的第一个空闲空间处：

[obj1][  obj3  ][obj5]
↑               ↑
p1           [...]&lt;img src=&quot;http://www1.feedsky.com/t1/597572845/siwei/feedsky/s.gif?r=http://wei.si/blog/2011/12/dotnet-gc-and-gc-knowledge-study-notes/&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</description><category>程序</category><pubDate>Thu, 01 Dec 2011 15:37:38 +0800</pubDate><author>Si Wei</author><comments>http://wei.si/blog/2011/12/dotnet-gc-and-gc-knowledge-study-notes/#comments</comments><guid isPermaLink="false">http://wei.si/blog/?p=643525</guid><dc:creator>Si Wei</dc:creator><fs:srclink>http://wei.si/blog/2011/12/dotnet-gc-and-gc-knowledge-study-notes/</fs:srclink><fs:srcfeed>http://wei.si/blog/feed/</fs:srcfeed><fs:itemid>feedsky/siwei/~8249691/597572845/1229498</fs:itemid></item></channel></rss>
