<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_winter-cn</title><subtitle type="text"/><id>http://feed.cnblogs.com/blog/u/37697/rss</id><updated>2012-01-28T03:32:15Z</updated><author><name>winter-cn</name><uri>http://www.cnblogs.com/winter-cn/</uri></author><generator>CNBlogs BlogServer</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/winter-cn/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/37697/rss"/><entry><id>http://www.cnblogs.com/winter-cn/archive/2012/01/27/2328512.html</id><title type="text">字符编码那点事儿</title><summary type="text">那时，天下人的口音、言语，都是一样。他们往东边迁移的时候，在示拿地遇见......——《创世记》 对于字符和编码的这点事，我自己蛋疼了很久，才渐渐理解了其中错综复杂的关系，这篇文章信息量不大，不过是个感性理解，希望对一些人会有帮助吧。</summary><published>2012-01-27T15:42:00Z</published><updated>2012-01-27T15:42:00Z</updated><author><name>winter-cn</name><uri>http://www.cnblogs.com/winter-cn/</uri></author><link rel="alternate" href="http://www.cnblogs.com/winter-cn/archive/2012/01/27/2328512.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/winter-cn/archive/2012/01/27/2328512.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;div&gt;&lt;div&gt;&lt;span style="font-weight: normal;"&gt;那时，天下人的口音、言语，都是一样。&lt;/span&gt;&lt;span style="font-weight: normal; "&gt;他们往东边迁移的时候，在示拿地遇见一片平原，就住在那里。&lt;/span&gt;&lt;span style="font-weight: normal; "&gt;他们彼此商量说：&amp;#8220;来吧！我们要作砖，把砖烧透了。&amp;#8221;他们就拿砖当石头，又拿石漆当灰泥。&lt;/span&gt;&lt;span style="font-weight: normal; "&gt;他们说：&amp;#8220;来吧！我们要建造一座城和一座塔，塔顶通天，为要传扬我们的名，免得我们分散在全地上。&amp;#8221;&lt;/span&gt;&lt;span style="font-weight: normal; "&gt;耶和华降临，要看看世人所建造的城和塔。&lt;/span&gt;&lt;span style="font-weight: normal; "&gt;耶和华说：&amp;#8220;看哪！他们成为一样的人民，都是一样的言语，如今既作起这事来，以后他们所要作的事，就没有不成就的了。&lt;/span&gt;&lt;span style="font-weight: normal; "&gt;我们下去，在那里变乱他们的口音，使他们的言语彼此不通。&amp;#8221;&lt;/span&gt;&lt;span style="font-weight: normal; "&gt;于是，耶和华使他们从那里分散在全地上；他们就停工不造那城了。&lt;/span&gt;&lt;span style="font-weight: normal; "&gt;因为耶和华在那里变乱天下人的言语，使众人分散在全地上，所以那城名叫巴别。&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;span style="font-weight: normal;"&gt;&amp;#8212;&amp;#8212;《创世记》&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;字符、字符集、字符编码&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;先说字符，字符大家都很清楚了，英文叫做character，通常的简写叫做char，字符加上一种字体（Font），就可以得到字型（Glyph），字型就是我们眼前所见之物了。&amp;nbsp;&lt;/p&gt;&lt;div&gt;字符用来在计算机领域表示语言和文字，世间有无穷多字符，如果沟通的双方要互相明白，就必须使用相同的字符集。字符集会规定一种或者几种用计算机字节表示字符的方法，这个方法就叫做字符编码。&amp;nbsp;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;ASCII&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;ASCII恐怕是最最著名的字符集了,至今为止还有人将ASCII误认为是计算机中表示字符的方法的代称，在任何编程系统中都会问"如何获取某一字符的ASCII码"。ASCII中共有127个字符，主要包含大小写英文字母、标点和一些控制符号。ASCII既是字符集，又是字符编码，ASCII的每个字符对应着0-127中的一个整数，这个整数称为字符的ASCII码。例如，字符'a'的ASCII码是97。&lt;/p&gt;&lt;p&gt;ASCII在计算机发展初期是非常NB的，这个时期主要是英语国家在使用计算机，而对当时的少数非英语国家用户而言，英语根本不成为门槛，ASCII编码可以放在一个Byte之中，这通常是计算机最小的空间单位。&lt;/p&gt;&lt;p&gt;哦对了，ASCII后来被国际标准化组织搞成了ISO/IEC 646，算是有了正式名分。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;ASCII兼容编码&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;因为ASCII对于英语之外的文字完全没有考虑，&amp;nbsp;所以显然没法满足全球人民日益增长的字符使用需要，而由于ASCII编码被广泛使用，所以又没法完完全全地重新发明一套新的字符集和编码方式。&lt;/p&gt;&lt;p&gt;注意到ASCII只占用了0-127，但是一个字节其实可以表示256个数字，于是128到255或者说-128到-1这些值被一些人开始盯上了。于是一些ASCII兼容编码开始出现了，其中我朝人民最为熟悉的就是GB2312了,unicode的UTF8编码方式也是ASCII兼容的，这些后文再详细分说。&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;ASCII兼容是向下兼容，即某种编码方式不需要经过任何转换接受任何以ASCII编码的文本为合法的，并且字符与当做ASCII编码时是完全一致的。&lt;/p&gt;&lt;p&gt;几乎所有的ASCII兼容编码方式都是变长编码，因为每个ASCII字符只占一个字节。&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;GB2312、GBK、GB18030&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;ASCII字符集里面不包括中文，那么显然这对于我国人民的感情来说是难以接受的，于是党和各级人民政府当然不会允许这种事情发生。在倪光南院士等人的关怀下，1980年具有独立自主知识产权的GB2312横空出世了。&lt;/p&gt;&lt;p&gt;1995年，在社会主义伟大旗帜下，有关部门组织一些专家对GB2312做了一些扩充，形成了GBK编码，也就是GB13000标准。&lt;/p&gt;&lt;p&gt;2000年，为了满足人民日益增长的字符使用需要，我国又制定了GB18030标准。&lt;/p&gt;&lt;p&gt;GB系列的编码还有一个称呼叫做区位码。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;ANSI&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;关于ANSI这种说不上是编码方式还是字符集的充满狗血故事的概念，还真是不太好讲。好吧首先ANSI的意思是American National Standards Institute，美国国家标准学会，嗯，但是很遗憾美国国家标准学会从来没有制定过这么一个标准，也不可能制定出来（好吧很快你就可以知道为什么了）。&lt;/p&gt;&lt;p&gt;最初这个东西如何出现，现在已经不可考证，但是毫无疑问至今windows的记事本保存选项里面仍然有这么一个叫做ANSI的选项。为什么说ANSI其实并不是一种字符集，也不是一个编码呢？因为实际上ANSI会随着操作系统的区域和语言设置而变化！当你将非unicode默认语言选成中文时，这个选项保存出来的文件赫然就是GB2312！对的！我认为ANSI这个词乃是米帝国主义亡我之心不死，妄图将伟大社会主义字符编码标准GB2312划入米国之手啊！&lt;/p&gt;&lt;p&gt;好吧，认真地说， ANSI这个概念颇为脑残，它的实际意思是遵循本地化设置的编码方式，但是却不伦不类地扯上了米国国家标准学会。&amp;nbsp;&lt;/p&gt;&lt;div&gt;&lt;p&gt;&lt;strong&gt;Unicode&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;讲字符编码一定不能漏了Unicode了，现在Unicode确实不负uni之名，是最有机会达成大统一重造巴别塔的一个字符集。Unicode的最新版本是6.0。&lt;/p&gt;&lt;p&gt;Unicode是一个字符集而不是一个编码方式，Unicode中每个字符对应一个code point(中译为码点，觉得不喜欢这个翻译) 。code point是一个0x00000到0x10FFFF之间的正整数。因此Unicode的字符都被记为U+XXXX，XXXX就是code point的16进制表示了。&lt;/p&gt;&lt;div&gt;Unicode还把code point分成17个code plane，其中主要使用的是0,1,2,3四个平面，也就是U+0000-U+FFFF，U+10000-U+1FFFF，U+20000-U+2FFFF，U+30000-U+3FFFF这四个code point的集合。&lt;/div&gt;&lt;p&gt;Unicode本身是抽象的，它发布的时候会带一个参考字型但是实际上它把字型的决定权交给了字体，所以code point就是字符的唯一标识了。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;UTF&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;unicode本身并非编码方式，所以unicode需要编码方式配合，常见的unicode编码方式就是UTF。UTF-X的数字X就表示最少用几个bit来表示一个字符。&lt;/p&gt;&lt;p&gt;常见的表示方式有UTF-8、UTF-16、UTF-32、UTF-7、UTF-24......&lt;/p&gt;&lt;p&gt;Unicode的&amp;nbsp;code plane共只有17个，所以UTF-32已经是定长编码了，它能表示的范围是0x00000000到0xFFFFFFFF，这显然远远超过现在Unicode的code point范围，所以短期内可以认为UTF-32是定长编码。定长编码的好处是，获取一个字符串的长度可以直接根据它占用的内存计算出，所以UTF家族中只有UTF-32可以享受到了。&lt;/p&gt;&lt;p&gt;UTF-8是最常用的UTF编码，特别地，它还是ASCII兼容的。&lt;/p&gt;&lt;p&gt;值得注意的是，这些编码里面，UTF-16使用甚广，因为unicode1.0发布的时候，&amp;nbsp;UTF-16还可以认为是定长编码，于是一些倒霉孩子比如Java就把UTF-16当成自己的字符串在内存中存储使用的编码，于是搞出来Char类型其实并不是每个表示一个字符，而是表示一个UTF-16 code unit这样的人间惨剧。&lt;/p&gt;&lt;p&gt;UTF-8对英文文本来说是非常合适的，但是中文每个文字要占三个字节，相比之下，UTF-16中的中文则是只占2个字节，所以当你的系统对存储容量或者网络流量敏感的时候，应该根据你的文本主要组成方式选择UTF恰当的编码。&lt;/p&gt;&lt;/div&gt;  &lt;p&gt;&lt;strong&gt;大端和小端&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;对于UTF-16、UTF-32这种东西而言，还有一个很现实的问题，它们的code unit都是一个正整数，而计算机系统的最小单位是字节，字节表示正整数是有高位低位顺序之分的，于是我们就有了大端小端的事情，相信用过window记事本的同学都有印象，里面有两个选项unicode big endian和unicode，实际上这里unicode指的就是UTF-16编码。&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;BOM&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;BOM又叫做Byte Order Mark，起因是我们的unicode里面规定了一个神奇的字符零宽空格U+FEFF，这个字符好啊，它明明是个字符，还显示不出来，于是一些程序员大爷想出了个nb的办法，约定所有的UTF数据流，都先吐出一个U+FEFF来，反正又不会显示出来，根据这个U+FEFF的表示方法，就可以判断数据流所使用的UTF编码了。比如说，收到三个字节&lt;span style="background-color: #ffffff; font-family: arial, 宋体, sans-serif; line-height: 24px; text-align: left; "&gt;EF BB BF的话，就可以断定来的编码是UTF-8了。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;这个NB办法后来也被推广到其它编码上（嗯，比如GB就不行，跟BOM冲突，打开记事本输入"联通"，然后保存为ANSI，再打开看看），也渐渐有了称呼叫做BOM。但是很遗憾，不少人不懂规矩，不会在数据源前面加BOM，于是天下间的文本，又被分为了有BOM和无BOM两种......&amp;nbsp;&lt;/p&gt;&lt;div&gt;&lt;p&gt;&lt;strong&gt;UCS&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;很多人说Unicode的标准是ISO16406，实际上这话不对，UCS才是。这中间有一段非常蛋疼的历史，unicode和ucs是分别由两个不同组织编写和发布的不同标准，但是因为二者在很早些时候就达成共识，一直紧密合作，始终默契地保持两份标准的一致，所以其实可以认为Unicode就是UCS了。&lt;/p&gt;&lt;/div&gt;&lt;p&gt;然而跟Unicode不同，UCS本身还规定了编码方式，主要有两种：UCS-2和UCS-4，这里的2和4表示最少用几个byte来表示一个字符。UCS-4也是定长编码，它跟UTF-32完全一致，所以二者只是理论上是两种编码而已。&lt;/p&gt;&lt;p&gt;值得注意的是，UCS-2与UTF-16是不完全一致的，UCS-2也是一种定长编码，code point超出0xFFFF的字符怎么办呢？UCS-2......它表示不了这些字符！&lt;/p&gt;&lt;p&gt;&lt;strong&gt;ISO-8859&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;实际上，制定了自己的编码标准的不仅仅是我们伟大的天朝，欧州国家也制定了一些自己的编码规范，它们都是针对特定地区的编码，不同语言使用不同字符集，所以互相之间不能混排，简单地说，就是跟GB2312一路货色，这些东西也就是前面提到过的ANSI编码了。&lt;/p&gt;&lt;p&gt;ISO-8859是一组规范，而不是一个规范，ISO-8859-1大家一定经常在各处见到，它表示西欧字符集。ISO-8859家族现在一共有15个，序号是从1排到16，除了12之外，关于为啥没有12有些不同说法，又说原本是要给加入&lt;span style="background-color: #ffffff; font-family: sans-serif; font-size: 15px; line-height: 22px; "&gt;塞尔特语族的Latin-7，也有说是留给印度天体梵文的，总之就是因为一些奇怪的原因跳过去了。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;很遗憾我朝大佬对于ISO毫无兴趣（也许ISO9001是例外？），因此GB始终是GB，没能加入ISO当中，不过GB基本可以认为是跟ISO-8859同一体系的一种编码。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;结语&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;对于字符和编码的这点事，我自己蛋疼了很久，才渐渐理解了其中错综复杂的关系，这篇文章信息量不大，不过是个感性理解，希望对一些人会有帮助吧。&amp;nbsp;&lt;/p&gt;&lt;div&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/winter-cn/aggbug/2328512.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/winter-cn/archive/2012/01/27/2328512.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/winter-cn/archive/2012/01/21/2328388.html</id><title type="text">C#字符串与享元（Flyweight）模式</title><summary type="text">写这个文章，主要是因为网上对C#字符串和享元模式的误解比较多。 Flyweight模式 先说这名字，fly呢，就是苍蝇，没错这里面不是飞的意思，是苍蝇的意思，weight大家都知道，就是重量，苍蝇的重量，就是非常非常轻的意思。所以Flyweight模式就是处理非常非常轻量级对象的一个东西。 Flyweight的目标是解决大量细粒度对象的内存消耗问题，当然，巧妇难为无米之炊，任何模式和手法都不能凭空造出内存来，所以享元模式针对的情况是这些细粒度对象的中数据有重复的情况。 Flyweight的做法是，把对象的状态（通常用属性表示），分成两个部分，一部分是内部状态，另一部分是外部状态。内部状...</summary><published>2012-01-20T18:09:00Z</published><updated>2012-01-20T18:09:00Z</updated><author><name>winter-cn</name><uri>http://www.cnblogs.com/winter-cn/</uri></author><link rel="alternate" href="http://www.cnblogs.com/winter-cn/archive/2012/01/21/2328388.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/winter-cn/archive/2012/01/21/2328388.html"/><content type="html">&lt;p&gt;写这个文章，主要是因为网上对C#字符串和享元模式的误解比较多。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Flyweight模式&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;先说这名字，fly呢，就是苍蝇，没错这里面不是飞的意思，是苍蝇的意思，weight大家都知道，就是重量，苍蝇的重量，就是非常非常轻的意思。所以Flyweight模式就是处理非常非常轻量级对象的一个东西。&lt;/p&gt;  &lt;p&gt;Flyweight的目标是解决大量细粒度对象的内存消耗问题，当然，巧妇难为无米之炊，任何模式和手法都不能凭空造出内存来，所以享元模式针对的情况是这些细粒度对象的中数据有重复的情况。&lt;/p&gt;  &lt;p&gt;Flyweight的做法是，把对象的状态（通常用属性表示），分成两个部分，一部分是内部状态，另一部分是外部状态。内部状态是不易重复的（或者说必要的），外部状态是易重复的。所以，Flyweight把外部状态提取出来共享，这样就一定程度解决了内存占用问题。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;C#中的字符串不是Flyweight模式&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;在网上常常可以看到一个说法，说C#中的字符串使用了Flyweight模式，开门见山地说，这个说法是错误的。&lt;/p&gt;  &lt;p&gt;错在哪里呢？按照上文的介绍，错就错在字符串它没有所谓的&amp;#8220;内部状态&amp;#8221;。&lt;/p&gt;  &lt;p&gt;通常讲字符串是享元的原因就是以下代码：&lt;/p&gt;  &lt;p&gt;string a = "Hello World";    &lt;br /&gt;Console.WriteLine(Object.ReferenceEquals(a, "Hello World")); //True&lt;/p&gt;  &lt;p&gt;当使用字符串直接量的时候，不论你写了多少个"Hello World"，最终内存里面只有一个字符串对象。&lt;/p&gt;  &lt;p&gt;运行时创建的字符串并不在此列，可以使些手段，强制在内存里面产生新的字符串。&lt;/p&gt;  &lt;p&gt;string a = "Hello World";    &lt;br /&gt;Console.WriteLine(Object.ReferenceEquals(a, new String("Hello World".ToCharArray())));&amp;nbsp; //False&lt;/p&gt;  &lt;p&gt;因为我们强行调用了new，所以这个字符串跟内存中的直接量"Hello World"对应的对象不是同一个。&lt;/p&gt;  &lt;p&gt;有趣的是，C#还允许强制把一个字符串加入到（如果已经有了，就只是找出来）字符串池里面。&lt;/p&gt;  &lt;p&gt;string a = "Hello World";    &lt;br /&gt;string b = String.Intern(new String("Hello World".ToCharArray()));     &lt;br /&gt;Console.WriteLine(Object.ReferenceEquals(a,b) );&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt;  &lt;p&gt;或者&lt;/p&gt;  &lt;p&gt;string a = String.Intern(new String("Hello World".ToCharArray()));    &lt;br /&gt;string b = String.Intern(new String("Hello World".ToCharArray()));     &lt;br /&gt;Console.WriteLine(Object.ReferenceEquals(a,b) );&lt;/p&gt;  &lt;p&gt;前面提到了，这个行为跟Flyweight使用的内部状态和外部状态不同，是两个对象实实在在就是同一个对象。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;C#中的字符串与Flyweight模式&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;好吧，前面说了不少，C#中的字符串不是Flyweight模式，但是是不是就意味着C#里面字符串跟Flyweight没有关系呢？&lt;/p&gt;  &lt;p&gt;当然不是，否则我写这么一篇文章岂不是太蛋疼了&amp;#8230;&amp;#8230;&lt;/p&gt;  &lt;p&gt;字符串池和Intern方法简直是实现Flyweight的神器啊！&lt;/p&gt;  &lt;p&gt;考虑我们有某一类对象，可能会创建几百万个，对象里面恰巧有这么一个属性叫做颜色，它在对象构造的时候随机产生，颜色用的是rgb色，用rgb24来表示，于是颜色字符串类似#ccc这样子。&lt;/p&gt;  &lt;p&gt;代码写起来就像下面的样子：&lt;/p&gt;  &lt;pre&gt;class Element&#xD;
    {&#xD;
	static Random rnd = new Random();&#xD;
	static char[] table;&#xD;
	static Element() &#xD;
	{&#xD;
	    table = "0123456789abcdef".ToCharArray();&#xD;
	}&#xD;
&#xD;
	public string color;&#xD;
	public Element()&#xD;
	{&#xD;
	    color = "" + table[rnd.Next() % 16] + table[rnd.Next() % 16] + table[rnd.Next() % 16];&#xD;
	}&#xD;
    }&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;接下来我们创建3千万个对象看看如何&lt;/p&gt;&#xD;
&#xD;
&lt;pre&gt;Element[] eles = new Element[30000000];&#xD;
	    for (var i = 0; i &amp;lt; 30000000; i++)&#xD;
	    {&#xD;
		eles[i] = new Element();&#xD;
	    }&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;从任务管理器看到一大块内存被吃掉了&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/winter-cn/201201/201201210209052078.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="QFOMR9}(NR%(T3`V3Q35MSY" border="0" alt="QFOMR9}(NR%(T3`V3Q35MSY" src="http://images.cnblogs.com/cnblogs_com/winter-cn/201201/201201210209066746.jpg" width="115" height="43" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;接下来我们使用String.Intern来实现Flyweight：&lt;/p&gt;&#xD;
&#xD;
&lt;pre&gt;class Element&#xD;
    {&#xD;
	static Random rnd = new Random();&#xD;
	static char[] table;&#xD;
	static Element() &#xD;
	{&#xD;
	    table = "0123456789abcdef".ToCharArray();&#xD;
	}&#xD;
&#xD;
	public string color;&#xD;
	public Element()&#xD;
	{&#xD;
	    color = String.Intern("" + table[rnd.Next() % 16] + table[rnd.Next() % 16] + table[rnd.Next() % 16]);&#xD;
	}&#xD;
    }&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;同样来看看运行结果：&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;br /&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/winter-cn/201201/201201210209067062.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="@XMI6L75IKU}S%NGI6L31@K" border="0" alt="@XMI6L75IKU}S%NGI6L31@K" src="http://images.cnblogs.com/cnblogs_com/winter-cn/201201/201201210209062601.jpg" width="111" height="35" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;可以看到内存占用量的明显变化。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;因为字符串对象的不可更改性质，使用了String.Intern之后，我们完全看不出前后color的区别，也就是说，修改前后的Element类是完全等效的，但是Flyweight为我们节约了大量的内存。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;更多思考&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;这个典型的使用flyweight场景为我们揭示了享元外部状态的特征：像字符串一样不可更改的对象。GoF原书的例子中的字型对象Glyph也是如此。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;String.Intern这种对象池的方式实现flyweight也值得借鉴，我们可以考虑自己设计flyweight的外部状态对象时使用类似的方式。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/winter-cn/aggbug/2328388.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/winter-cn/archive/2012/01/21/2328388.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/winter-cn/archive/2011/07/20/LR1.html</id><title type="text">语法分析算法LR(1)基础教程（上）</title><summary type="text">现在网上能找到的大部分将语法分析的文章都是LL的，而本文专门讲不太常见的LR(1)</summary><published>2011-07-19T19:26:00Z</published><updated>2011-07-19T19:26:00Z</updated><author><name>winter-cn</name><uri>http://www.cnblogs.com/winter-cn/</uri></author><link rel="alternate" href="http://www.cnblogs.com/winter-cn/archive/2011/07/20/LR1.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/winter-cn/archive/2011/07/20/LR1.html"/><content type="html">讨厌英文的同学，请&lt;a href="javascript:replace(dict_en);void 0;"&gt;点我碰碰运气&lt;/a&gt; &lt;br /&gt;&#xD;
不小心乱玩后悔了的话，请&lt;a href="javascript:replace(dict_zh);void 0;"&gt;再碰碰运气&lt;/a&gt;，说不定会恢复&#xD;
&lt;p&gt;&lt;strong&gt;基本概念&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;首先解释一下基本概念&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;词法分析和语法分析&lt;/strong&gt;：编译或者解释一门语言，必经两个步骤：词法分析和语法分析，词法分析就是把源代码的字符流变成计算机可理解的词汇：token，语法分析就是把token流变成一颗结构化的语法树，以便后面的程序去翻译或者分析。比如，假如计算机要想识别整﻿数四则运算，词法分析器那么就要认识整﻿数、加减乘除四种运算符号，以及左右括号这些token，而要根据运算符的结合性，把四则运算构建成语法树。&lt;/p&gt;&#xD;
&lt;p&gt;3 + 4 &amp;#215; 5&lt;/p&gt;&#xD;
&lt;p&gt;最后得到的语法树可能长成下面的样子&lt;/p&gt;&#xD;
&lt;p&gt;AdditiveExpression:&lt;/p&gt;&#xD;
&lt;p&gt;AdditiveExpression&lt;/p&gt;&#xD;
&lt;p&gt;MultipleExpression:&lt;/p&gt;&#xD;
&lt;p&gt;Integer:3&lt;/p&gt;&#xD;
&lt;p&gt;"+"&lt;/p&gt;&#xD;
&lt;p&gt;MultipleExpression:&lt;/p&gt;&#xD;
&lt;p&gt;Integer:4&lt;/p&gt;&#xD;
&lt;p&gt;"&amp;#215;"&lt;/p&gt;&#xD;
&lt;p&gt;Integer:5&lt;/p&gt;&#xD;
&lt;p&gt;上面这颗树用编程语言中的数据结构表达出来，就是比较容易被计算机理解和处理的了。（设计模式中的Interpreter模式，就是省略前面的步骤直接使用这种结构的）&lt;/p&gt;&#xD;
&lt;p&gt;词法分析可以简单地用正则表﻿达式来完成，而本文则专门讲一种语法分析的经典算法：LR(1)&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;定义语法&amp;#8212;&amp;#8212;BNF/EBNF&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;上面我们提到了四则运算，不过我们没有严格定义四则运算到底是什么，比如，有没有括号、用&amp;#215;还是*来表示乘法，但是计算机语言需要一个非常严谨的定义方式，现在广泛使用的就是BNF及其扩展EBNF。如我们以以下方式定义带括号四则运算：&lt;/p&gt;&#xD;
&lt;p&gt;&amp;lt;Expression&amp;gt; ::= &amp;lt;AdditiveExpression&amp;gt;&lt;/p&gt;&#xD;
&lt;p&gt;&amp;lt;AdditiveExpression&amp;gt; ::=&amp;nbsp; &amp;lt;AdditiveExpression&amp;gt; "+" &amp;lt;MultipleExpression&amp;gt; | &amp;lt;AdditiveExpression&amp;gt; "-" &amp;lt;MultipleExpression&amp;gt; | &amp;lt;MultipleExpression&amp;gt;&lt;/p&gt;&#xD;
&lt;p&gt;&amp;lt;MultipleExpression&amp;gt; ::= &amp;lt;MultipleExpression&amp;gt; "&amp;#215;" &amp;lt;PrimaryExpression&amp;gt; | &amp;lt;MultipleExpression&amp;gt; "/" &amp;lt;PrimaryExpression&amp;gt; | &amp;lt;PrimaryExpression&amp;gt;&lt;/p&gt;&#xD;
&lt;p&gt;&amp;lt;PrimaryExpression&amp;gt; ::= "(" &amp;lt;Expression&amp;gt; ")" | &amp;lt;Integer&amp;gt;&lt;/p&gt;&#xD;
&lt;p&gt;其中Expression、AdditiveExpression、MultipleExpression 、PrimaryExpression、Integer我们成为Symbol(语法符号，C++链接器报的错误里面说找不到符号，就是这个词)，词法分析产生的每一个token也同时是Symbol，如果一个Symbol可以由若干个Symbol组成，那么称为non-terminal symbol（非终结符），否则称terminal symbol，最后生成语法树以后，terminal symbol就是所有的叶子节点。&lt;/p&gt;&#xD;
&lt;p&gt;因为对BNF的一些批评，后来出现了EBNF,它是BNF的扩展版本。&lt;/p&gt;&#xD;
&lt;p&gt;Expression ::= AdditiveExpression&lt;/p&gt;&#xD;
&lt;p&gt;AdditiveExpression ::=&amp;nbsp; AdditiveExpression "+" MultipleExpression , AdditiveExpression "-" MultipleExpression , MultipleExpression&lt;/p&gt;&#xD;
&lt;p&gt;MultipleExpression ::= MultipleExpression "&amp;#215;" PrimaryExpression , MultipleExpression "&amp;#247;" PrimaryExpression , PrimaryExpression&lt;/p&gt;&#xD;
&lt;p&gt;PrimaryExpression ::= "(" Expression ")" , Integer&lt;/p&gt;&#xD;
&lt;p&gt;在现在大多数语言规范中，都在使用BNF/EBNF或者与之非常接近的方法来描述语法。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;LL与LR&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;常见的语法分析算法有LL和LR。&lt;/p&gt;&#xD;
&lt;p&gt;LL的第一个L表示from Left to right，第二个L表示Left most推导。&lt;/p&gt;&#xD;
&lt;p&gt;LR的第一个L和LL的第一个L含义相同，第二个R表示Right most推导。 &lt;/p&gt;&#xD;
&lt;p&gt;在通常的描述中，后面还有一个括号里面的数字如，LL(0)、LL(1)、LL(4)、LR(0)、LR(1)这样，括号里面的数字表示用于决策所需的后续token数。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;pre&gt;&lt;/pre&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;LR(1)状态机构建&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;LR(1)分析从外部看起来，每次接受一个字符，最后接收程序终结符时，内部刚好形成一颗语法树。&lt;/p&gt;&#xD;
&lt;p&gt;在内部，每当我们接受一个Symbol之后，我们就需要做一个决定：是把新的Symbol跟原有的Symbol立即合并成更高级的Symbol，还是把新的Symbol暂放呢？&lt;/p&gt;&#xD;
&lt;p&gt;在LR(1)中，有两个术语：reduce(归约)和shift(移入)。规约就是把已经读入的低级Symbol组合成高级Symbol，如Integer "x" Integer 可以reduce成MultipleExpression &lt;/p&gt;&#xD;
&lt;p&gt;仍然以上面的 3 + 4 &amp;#215; 5 为例，当我们接受3的时候，实际上3已经是一个完整的PrimaryExpression了,而进一步，一个PrimaryExpression也是MultipleExpression，我们可以一直将3归约到一个完整的Expression&lt;/p&gt;&#xD;
&lt;p&gt;Expression:&lt;/p&gt;&#xD;
&lt;p&gt;AdditiveExpression:&lt;/p&gt;&#xD;
&lt;p&gt;MultipleExpression:&lt;/p&gt;&#xD;
&lt;p&gt;PrimaryExpression:&lt;/p&gt;&#xD;
&lt;p&gt;Integer:3&lt;/p&gt;&#xD;
&lt;p&gt;但是我们此时不应当直接reduce到Expression，这是一个错误的语法树结构。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;考虑以下两种情况：&lt;/p&gt;&#xD;
&lt;p&gt;3 + 4 &amp;#215; 5，在读入&amp;#215;时，&lt;/p&gt;&#xD;
&lt;p&gt;此时 3 + 4显然不应该被reduce&lt;/p&gt;&#xD;
&lt;p&gt;3 &amp;#215; 4 + 5，在读入+时&lt;/p&gt;&#xD;
&lt;p&gt;此时 3 &amp;#215; 4 显然应该被reduce&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;为了正确处理以上的问题，我们要构建一个状态机来指导LR(1)运算，何时reduce，何时shift。&lt;/p&gt;&#xD;
&lt;p&gt;由BNF我们可以得到的语法规则，以四则运算为例，最终我们想要的是一个Expression，即我们的语法树最终根节点是Expression 。&lt;/p&gt;&#xD;
&lt;p&gt;我们认为输入的token序列最终会形成一个Expression，那么考虑一个问题，状态机的最初状态0，能够接受哪些Symbol的shift呢？&lt;/p&gt;&#xD;
&lt;p&gt;第一个考虑到，状态机可以接受Expression这个Symbol,这将导致我们进入最终状态。&lt;/p&gt;&#xD;
&lt;p&gt;此外因为有语法规则Expression ::= AdditiveExpression，状态0还能接受AdditiveExpression&lt;/p&gt;&#xD;
&lt;p&gt;又因为有语法规则AdditiveExpression ::=&amp;nbsp; MultipleExpression "+" MultipleExpression , MultipleExpression "-" MultipleExpression , MultipleExpression&lt;/p&gt;&#xD;
&lt;p&gt;状态0还能接受MultipleExpression &lt;/p&gt;&#xD;
&lt;p&gt;&amp;#8230;&amp;#8230;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;从这个分析过程不难看出，状态0可以接受所有Expression，以及所有能生成Expression的规则的第一个Symbol，并按此规则递归。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;接下来我们要关心迁移问题了，毫无疑问接受Expression这个Symbol以后，直接进入最终状态，然而对于其它情况，如接受了一个MultipleExpression ，则会产生更多可能性，我们把AdditiveExpression ::=&amp;nbsp; MultipleExpression "+" MultipleExpression , MultipleExpression "-" MultipleExpression , MultipleExpression看成3条规则，把所有的规则全都拆分出来.&lt;/p&gt;&#xD;
&lt;p&gt;每一条规则都将会形成若干状态迁移规则：&lt;/p&gt;&#xD;
&lt;hr /&gt;&#xD;
&lt;p&gt;&lt;strong&gt;Expression ::= AdditiveExpression&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&amp;#9679; AdditiveExpression &lt;/p&gt;&#xD;
&lt;p&gt;AdditiveExpression &amp;#9679;&lt;/p&gt;&#xD;
&lt;hr /&gt;&#xD;
&lt;p&gt;&lt;strong&gt;AdditiveExpression ::=&amp;nbsp; AdditiveExpression "+" MultipleExpression , AdditiveExpression "-" MultipleExpression , MultipleExpression&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&amp;#9679; AdditiveExpression "+" MultipleExpression&lt;/p&gt;&#xD;
&lt;p&gt;AdditiveExpression &amp;#9679; "+" MultipleExpression&lt;/p&gt;&#xD;
&lt;p&gt;AdditiveExpression "+" &amp;#9679; MultipleExpression&lt;/p&gt;&#xD;
&lt;p&gt;AdditiveExpression "+" MultipleExpression &amp;#9679; &lt;/p&gt;&#xD;
&lt;p&gt;&amp;#9679; AdditiveExpression "-" MultipleExpression &lt;/p&gt;&#xD;
&lt;p&gt;AdditiveExpression &amp;#9679; "-" MultipleExpression &lt;/p&gt;&#xD;
&lt;p&gt;AdditiveExpression "-" &amp;#9679; MultipleExpression &lt;/p&gt;&#xD;
&lt;p&gt;AdditiveExpression "-" MultipleExpression &amp;#9679;&lt;/p&gt;&#xD;
&lt;p&gt;&amp;#9679; MultipleExpression&lt;/p&gt;&#xD;
&lt;p&gt;MultipleExpression &amp;#9679;&lt;/p&gt;&#xD;
&lt;hr /&gt;&#xD;
&lt;strong&gt;MultipleExpression ::= MultipleExpression "&amp;#215;" PrimaryExpression , MultipleExpression "&amp;#247;" PrimaryExpression , PrimaryExpression&lt;/strong&gt;&#xD;
&lt;p&gt;&amp;#9679; MultipleExpression "&amp;#215;" PrimaryExpression &lt;/p&gt;&#xD;
&lt;p&gt;MultipleExpression &amp;#9679; "&amp;#215;" PrimaryExpression &lt;/p&gt;&#xD;
&lt;p&gt;MultipleExpression "&amp;#215;" &amp;#9679; PrimaryExpression &lt;/p&gt;&#xD;
&lt;p&gt;MultipleExpression "&amp;#215;" PrimaryExpression &amp;#9679;&lt;/p&gt;&#xD;
&lt;p&gt;&amp;#9679; MultipleExpression "&amp;#247;" PrimaryExpression &lt;/p&gt;&#xD;
&lt;p&gt;MultipleExpression &amp;#9679; "&amp;#247;" PrimaryExpression &lt;/p&gt;&#xD;
&lt;p&gt;MultipleExpression "&amp;#247;" &amp;#9679; PrimaryExpression &lt;/p&gt;&#xD;
&lt;p&gt;MultipleExpression "&amp;#247;" PrimaryExpression &amp;#9679; &lt;/p&gt;&#xD;
&lt;p&gt;&amp;#9679; PrimaryExpression&lt;/p&gt;&#xD;
&lt;p&gt;PrimaryExpression &amp;#9679;&lt;/p&gt;&#xD;
&lt;hr /&gt;&#xD;
&lt;p&gt;&lt;strong&gt;PrimaryExpression ::= "(" Expression ")" , Integer&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&amp;#9679; "(" Expression ")" &lt;/p&gt;&#xD;
&lt;p&gt;"(" &amp;#9679; Expression ")" &lt;/p&gt;&#xD;
&lt;p&gt;"(" Expression &amp;#9679; ")" &lt;/p&gt;&#xD;
&lt;p&gt;"(" Expression ")" &amp;#9679;&lt;/p&gt;&#xD;
&lt;p&gt;&amp;#9679; Integer&lt;/p&gt;&#xD;
&lt;p&gt;Integer &amp;#9679;&lt;/p&gt;&#xD;
&lt;hr /&gt;&#xD;
&lt;p&gt;显而易见，我们可以总结出下面两条规律：&lt;/p&gt;&#xD;
&lt;ol&gt;&#xD;
     &lt;li&gt;所有以&amp;#9679;结尾的状态，操作就是规约,其它状态操作就是移入。&lt;/li&gt;&#xD;
     &lt;li&gt;假如当前状态&amp;#9679; 后是一个非终结符X，那么所有能规约到X的规则中以&amp;#9679;开头的状态迁移规则也适用于当前状态。&lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;p&gt;我们现在可以认为&amp;#9679; Expression是初始状态，Expression &amp;#9679; 是结束状态，根据规则2，可以得到以下状态迁移适用当前状态&lt;/p&gt;&#xD;
&lt;p&gt;&amp;#9679; AdditiveExpression&lt;/p&gt;&#xD;
&lt;p&gt;&amp;#9679; AdditiveExpression "+" MultipleExpression&lt;/p&gt;&#xD;
&lt;p&gt;&amp;#9679; AdditiveExpression "-" MultipleExpression &lt;/p&gt;&#xD;
&lt;p&gt;&amp;#9679; MultipleExpression&lt;/p&gt;&#xD;
&lt;p&gt;&amp;#9679; MultipleExpression "&amp;#215;" PrimaryExpression&lt;/p&gt;&#xD;
&lt;p&gt;&amp;#9679; MultipleExpression "&amp;#247;" PrimaryExpression &lt;/p&gt;&#xD;
&lt;p&gt;&amp;#9679; PrimaryExpression&lt;/p&gt;&#xD;
&lt;p&gt;&amp;#9679; "(" Expression ")" &lt;/p&gt;&#xD;
&lt;p&gt;&amp;#9679; Integer&lt;/p&gt;&#xD;
&lt;p&gt;同样开头的迁移规则必须归并，实际上，第一次我们可以得到JSON表示的以下状态结构(我们用JS程序员最喜欢的$表示reduce)&lt;/p&gt;&#xD;
&lt;p&gt;{&lt;/p&gt;&#xD;
&lt;p&gt;AdditiveExpression:{&lt;/p&gt;&#xD;
&lt;p&gt;"+": {MultipleExpression:{$:"AdditiveExpression"}},&lt;/p&gt;&#xD;
&lt;p&gt;"-": {MultipleExpression:{$:"AdditiveExpression"}},&lt;/p&gt;&#xD;
&lt;p&gt;$: "Expression"&lt;/p&gt;&#xD;
&lt;p&gt;},&lt;/p&gt;&#xD;
&lt;p&gt;MultipleExpression:{&lt;/p&gt;&#xD;
&lt;p&gt;"&amp;#215;": {PrimaryExpression:{$:"MultipleExpression"}},&lt;/p&gt;&#xD;
&lt;p&gt;"&amp;#247;": {PrimaryExpression:{$:"MultipleExpression"}},&lt;/p&gt;&#xD;
&lt;p&gt;$: "AdditiveExpression"&lt;/p&gt;&#xD;
&lt;p&gt;},&lt;/p&gt;&#xD;
&lt;p&gt;PrimaryExpression:{$:"MultipleExpression"},&lt;/p&gt;&#xD;
&lt;p&gt;"(":{Expression:{")":{$:"PrimaryExpression"}}},&lt;/p&gt;&#xD;
&lt;p&gt;Integer:{$:"PrimaryExpression"}&lt;/p&gt;&#xD;
&lt;p&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;注意，这个状态迁移关系仅仅是分析了第一个状态后的结果，要想得到完整地状态机，还要对所有后续状态递归地应用规则2。这将可能产生无限循环，为了避免这种情况，我们应该对每个状态做hash,然后把循环的情况直接指向之前的结果。&lt;/p&gt;&#xD;
&lt;p&gt;做完这些之后，我们就得到了一个完整的LR(1)状态机。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;下篇：LR(1)分析过程&lt;/strong&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/winter-cn/aggbug/2111192.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/winter-cn/archive/2011/07/20/LR1.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/winter-cn/archive/2011/05/03/2035914.html</id><title type="text">驳“面向对象的基本特性多态”</title><summary type="text">在网上常常能看到文章讲面向对象的三大基本特征"继承"、"封装"、"多态"，我以为这是坊间流传的最不靠谱的一个说法。本文先谈谈其中讲到的一个特性：多态。多态是一个跟面向对象完全正交的概念，两者之间可以说没有任何必然联系。</summary><published>2011-05-03T13:57:00Z</published><updated>2011-05-03T13:57:00Z</updated><author><name>winter-cn</name><uri>http://www.cnblogs.com/winter-cn/</uri></author><link rel="alternate" href="http://www.cnblogs.com/winter-cn/archive/2011/05/03/2035914.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/winter-cn/archive/2011/05/03/2035914.html"/><content type="html">&lt;p&gt;在网上常常能看到文章讲面向对象的三大基本特征"继承"、"封装"、"多态"，我以为这是坊间流传的最不靠谱的一个说法。本文先谈谈其中讲到的一个特性：多态。多态是一个跟面向对象完全正交的概念，两者之间可以说没有任何必然联系。当然口说无凭，下面是我经过很长时间查找到的一些来源比较可靠的资料对多态的说法。&lt;/p&gt;&lt;p&gt;最早可查证的关于多态的说法是一篇叫做&amp;nbsp;Fundamental Concepts in Programming Languages的论文，文中对多态的讨论主要是用于实现运算符的重载版本选择，文中把多态分为两种：&amp;nbsp;ad-hoc多态和参数多态，ad-hoc多态即指系统根据上下文自己决定如何选择运算符的行为，比如各种原生的运算符都在此列。参数多态则是根据参数类型选择。文中对参数多态的解释则是用了一个颇为"函数式"的例子，根据传入的函数类型参数的函数签名来决定返回值类型。&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;&lt;div&gt;1985年左右的一篇论文On Understanding Types,&amp;nbsp;Data Abstraction, and Polymorphis则详细地论述总结了多态性的概念，文中给出了多态的分类：&lt;/div&gt;&lt;div&gt;&lt;div&gt;polymorphism(多态)&lt;/div&gt;&lt;div&gt;|-universal&lt;/div&gt;&lt;p&gt;| |-&amp;nbsp;parametric&amp;nbsp;&lt;/p&gt;&lt;p&gt;| \-&amp;nbsp;inclusion&lt;/p&gt;&lt;div&gt;\-ad-hoc&lt;/div&gt;&lt;p&gt;|-&amp;nbsp;overloading&lt;/p&gt;&lt;p&gt;\-&amp;nbsp;coercio&amp;nbsp;&lt;/p&gt;&lt;div&gt;这篇文章对多态的论述比较系统，网上也有pdf版本，有兴趣的朋友可以详细阅读。(inclusion多态听起来比较陌生，但是其实它的另一个名称是subtype&amp;nbsp;Polymorphism,这也是唯一一种跟面向对象相关的多态)&lt;/div&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;从上面的发展可以看出，多态是一个差不多跟面向对象同时（60年代）诞生的编程概念，有自己独立的体系结构，并且这个概念非常广泛地用于很多种编程语言的设计当中。&lt;/p&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; "&gt;关于面向对象跟多态的关系，下面一段话用来解释非常恰当（来自The C++ programming language），&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;p&gt;Since both(wintercn注：根据上下文指template和abstract class) allow an algorithm to be expressed once and applied to a variety of types, people&amp;nbsp;sometimes refer to both as polymorphic.&amp;nbsp;&lt;/p&gt;&lt;p&gt;意思是：因为template和abstract class两种机制都能允许一个算法表达一次而用在多种不同类型当中，所以人们把两种都称作多态。后文还讲到abstract class提供的是运行时多态，template提供的是编译时多态。（有趣的是，连面向对象的代表性语言之一C++本身都涉及到了一种跟面向对象毫无关系的多态类型。）&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;所以事实上，多态并非面向对象的私产，更不是什么面向对象的基本特征，多态和面向对象的关系是：面向对象中的抽象类，提供了一种运行时多态的实现方式。&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/winter-cn/aggbug/2035914.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/winter-cn/archive/2011/05/03/2035914.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/winter-cn/archive/2011/03/01/1960267.html</id><title type="text">面试时算法题的解答思路</title><summary type="text">面试中纯粹考算法的问题一般是让很多程序员朋友痛恨的，这里分享下我对于解答算法题的一些思路和技巧。一般关于算法的文章，都是从经典算法讲起，一种一种算法介绍，见得算法多了，自然就有了感悟，但如此学习花费的时间和精力却是过于巨大，也不适合在博客里面交流。这一篇文，却是专门讲快捷思路的，很多人面对算法题的时候几乎是脑子里一片空白，这一篇文章讲的就是从题目下手，把毫无思路的题目打开一个缺口的几种常见技巧。</summary><published>2011-02-28T19:44:00Z</published><updated>2011-02-28T19:44:00Z</updated><author><name>winter-cn</name><uri>http://www.cnblogs.com/winter-cn/</uri></author><link rel="alternate" href="http://www.cnblogs.com/winter-cn/archive/2011/03/01/1960267.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/winter-cn/archive/2011/03/01/1960267.html"/><content type="html">&lt;p&gt;面试中纯粹考算法的问题一般是让很多程序员朋友痛恨的，这里分享下我对于解答算法题的一些思路和技巧。&lt;/p&gt;&#xD;
&lt;p&gt;一般关于算法的文章，都是从经典算法讲起，一种一种算法介绍，见得算法多了，自然就有了感悟，但如此学习花费的时间和精力却是过于巨大，也不适合在博客里面交流。这一篇文，却是专门讲快捷思路的，很多人面对算法题的时候几乎是脑子里一片空白，这一篇文章讲的就是从题目下手，把毫无思路的题目打开一个缺口的几种常见技巧。&lt;/p&gt;&#xD;
&lt;p&gt;（一）由简至繁&lt;/p&gt;&#xD;
&lt;p&gt;事实上，很多问题确实是很难在第一时间内得到正确的思路的，这时候可以尝试一种由简至繁的思路。首先把问题规模缩小到非常容易解答的地步。&lt;/p&gt;&#xD;
&lt;p&gt;[题目]有足够量的2分、5分、1分硬币，请问凑齐1元钱有多少种方法？&lt;/p&gt;&#xD;
&lt;p&gt;此题乍看上去，只会觉得完全无法入手，但是按照由简至繁的思路，我们可以先考虑极端简单的情况，假如把问题规模缩小成:有足够量的1分硬币，请问凑齐1分钱有多少种方法？毫无疑问，答案是1。&lt;/p&gt;&#xD;
&lt;p&gt;得到这一答案之后，我们可以略微扩大问题的规模： 有足够量的1分硬币，凑齐2分钱有多少种方法？凑齐n分钱有多少种方法？答案仍然是1&lt;/p&gt;&#xD;
&lt;p&gt;接下来，我们可以从另一个角度来扩大问题，有足够量的1分硬币和2分硬币，凑齐n分钱有多少种方法？这时我们手里已经有了有足够量的1分硬币，凑齐任意多钱都只有1种方法，那么只用1分钱凑齐n-2分钱，有1种方法，只用1分钱凑齐n-4分钱，有1种方法，只用1分钱凑齐n-6分钱，有1种方法......&lt;/p&gt;&#xD;
&lt;p&gt;而凑齐这些n-2、n-4、n-6这些钱数，各自补上2分钱，会产生一种新的凑齐n分钱的方法，这些方法的总数+1，就是用1分硬币和2分硬币，凑齐n分钱的方法数了。&lt;/p&gt;&#xD;
&lt;p&gt;在面试时，立刻采用这种思路是一种非常有益的尝试，解决小规模问题可以让你更加熟悉问题，并且慢慢发现问题的特性，最重要的是给你的面试官正面的信号&amp;#8212;&amp;#8212;立即动手分析问题比皱眉冥思苦想看起来好得多。&lt;/p&gt;&#xD;
&lt;p&gt;对于此题而言，我们可以很快发现问题的规模有两个维度：用a1-ak种硬币和凑齐n分钱，所以我们可以记做P(k,n)。当我们发现递归公式 P(k,n) = P(k-1,n - ak) + P(k-1,n - 2*ak) + P(k-1,n - 3*ak) ... ... 时，这个问题已经是迎刃而解了&lt;/p&gt;&#xD;
&lt;p&gt;通常由简至繁的思路，用来解决动态规划问题是非常有效的，当积累了一定量简单问题的解的时候，往往通向更高一层问题的答案已经摆在眼前了。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;（二）一分为二&lt;/p&gt;&#xD;
&lt;p&gt;另一种思路，就是把问题一刀斩下，把问题分为两半，变成两个与原来问题同构的问题，能把问题一分为2，就能再一分为4，就能再一分为8，直到分成我们容易解决的问题。当尝试这种思路时，其实只需要考虑两个问题：1.一分为二以后，问题是否被简化了？ 2.根据一分为二的两个问题的解，能否方便地得出整个问题的解？&lt;/p&gt;&#xD;
&lt;p&gt;[题目]将一个数组排序。&lt;/p&gt;&#xD;
&lt;p&gt;这个经典算法肯定所有人都熟悉的不能再熟悉了，不过若是从头开始思考这个问题，倒也不是所有人都能想出几种经典的排序算法之一的，这里仅仅是用来做例子说明一分为二的思路的应用。&lt;/p&gt;&#xD;
&lt;p&gt;最简单的一分为二，就是将数组分成两半，分别排序。对于两个有序数组，我们有办法将它合并成一个有序数组，所以这个一分为二的思路是可行的，同样对于已经分成两半的数组，我们还可以将这个数组分作两半，直到我们分好的数组仅有1个元素，1个元素的数组天然就是有序的。不难看出，按这种思路我们得出的是经典数组排序算法中的&amp;#8220;归并排序&amp;#8221;。&lt;/p&gt;&#xD;
&lt;p&gt;还有另一种一分为二的思路，考虑到自然将数组分成两半合并起来比较复杂，我们可以考虑将数组按照大于和小于某个元素分成两半，这样只要分别解决就可以直接连接成一个有序数组了，同样这个问题也是能够再次一分为二。按照这个思路，则可以得出经典数组排序算法中的&amp;#8220;快速排序&amp;#8221;。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;（三）化虚为实&lt;/p&gt;&#xD;
&lt;p&gt;这种思路针对的是浮点数有关的特殊问题，因为无论是穷举还是二分，对于浮点数相关的计算问题（尤其是计算几何）都难以启效，所以化虚为实，指的是把有点"虚"的浮点数，用整数来替代。具体做法是，把题目中给出的一些浮点数（不限于浮点数，我们不关心其具体大小的整数也可以）排序，然后用浮点数的序号代替本身来思考问题，等到具体计算时再替换回来。&lt;/p&gt;&#xD;
&lt;p&gt;[题目]已知n个边水平竖直的矩形（用四元组[x1,y1,x2,y2]表示），求它们的总共覆盖面积。&lt;/p&gt;&#xD;
&lt;p&gt;因为坐标可能出现浮点数，所以此题看起来十分繁复（可以实践上面由简至繁和一分为二的思路都基本无效），略一思考，矩形的覆盖关系其实只跟矩形坐标的大小有关，所以我们尝试思考将矩形的所有x值排序，然后用序号代替具体竖直，y值亦然，于是我们得到所有矩形其实处于一个2nx2n的区块当中，这样我们用最简单的穷举办法，可以计算出每一个1x1的格子是否被覆盖住了。至此，只要我们计算面积的时候，把格子的真实长宽换算回来，就已经得到题目的答案了。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;本文是某天在QQ群里讨论面试时的算法问题时想到要写的，以上三种思路，是我平时遇到算法问题的快速思考方向，并非万灵药方，若是不能生效，就要静下心来慢慢思考观察了，考虑到面试的时候基本不会遇到高难度算法题，这几种技巧的命中率应该不会太低，共享给大家，希望有所帮助。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/winter-cn/aggbug/1960267.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/winter-cn/archive/2011/03/01/1960267.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/winter-cn/archive/2010/12/29/1919266.html</id><title type="text">CSS3:transform与transition背后的数学原理</title><summary type="text">简单介绍了CSS3中的新属性transform与transition背后的数学原理，主要涉及2D矩阵变换和贝塞尔插值</summary><published>2010-12-28T16:20:00Z</published><updated>2010-12-28T16:20:00Z</updated><author><name>winter-cn</name><uri>http://www.cnblogs.com/winter-cn/</uri></author><link rel="alternate" href="http://www.cnblogs.com/winter-cn/archive/2010/12/29/1919266.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/winter-cn/archive/2010/12/29/1919266.html"/><content type="html">&lt;div style="layout-grid:  15.6pt none" &gt;   &lt;p&gt;(很多同学看到大段的数学公式就会发昏，我以人格担保，这里面的数学公式简单的不能再简单了......)&lt;/p&gt;    &lt;p&gt;transform的原理是计算机图形学中的2D矩阵变换，&lt;/p&gt;    &lt;p&gt;在开始之前，首先来复习下一个简单的线性代数知识：矩阵与向量乘法。太复的用不到，只需要3维向量与3x3矩阵的乘积：&lt;/p&gt;    &lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image001" border="0" alt="image001" src="http://images.cnblogs.com/cnblogs_com/winter-cn/201101/201101021501242466.png" width="653" height="83" /&gt;&lt;/p&gt;    &lt;p&gt;接下来我们来说说transform跟矩阵乘法的关系，我们的任何一个html元素渲染完成后可以得到一张位图，把这张位图上所有的点都做一次矩阵运算，将得到一张的新的位图，这就是transform的基本含义。&lt;/p&gt;    &lt;p&gt;首先来看最简单的transform，translate。我们都知道tansform:translate(tx,ty);的基本含义是将一个元素的显示位置平移tx,ty。在矩阵变换中，translate体现为下面的矩阵运算：&lt;/p&gt;    &lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image002" border="0" alt="image002" src="http://images.cnblogs.com/cnblogs_com/winter-cn/201101/201101021501258812.png" width="230" height="62" /&gt;&lt;/p&gt;    &lt;p&gt;tansform:scale(sx,sy);将一个元素拉伸或者压缩指定的倍数，它对应的矩阵变换是：&lt;/p&gt;    &lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image003" border="0" alt="image003" src="http://images.cnblogs.com/cnblogs_com/winter-cn/201101/201101021501278581.png" width="238" height="62" /&gt;&lt;/p&gt;    &lt;p&gt;transform:rotate(a)将一个元素旋转角度a，它对应的矩阵变换是：&lt;/p&gt;    &lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image004" border="0" alt="image004" src="http://images.cnblogs.com/cnblogs_com/winter-cn/201101/201101021501282593.png" width="450" height="62" /&gt;&lt;/p&gt;    &lt;p&gt;transform:skew(ax,ay)将一个元素研x向和y向倾斜角度ax和ay，它对应的矩阵变换是：&lt;/p&gt;    &lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image005" border="0" alt="image005" src="http://images.cnblogs.com/cnblogs_com/winter-cn/201101/201101021501292527.png" width="380" height="62" /&gt;&lt;/p&gt;    &lt;p&gt;transform:matrix(a,b,c,d,e,f)则是完整的矩阵变换，把这张位图上所有的点都做一次矩阵乘法，得到的新位图&lt;/p&gt;    &lt;p&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image006" border="0" alt="image006" src="http://images.cnblogs.com/cnblogs_com/winter-cn/201101/201101021501306855.png" width="359" height="62" /&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;transition涉及到的则是另一个数学概念：贝塞尔插值。&lt;/p&gt;    &lt;p&gt;transition的变换函数有 linear ease ease-in ease-out ease-in-out几种，通常我们尝试使用时能感觉到它们之间稍有不同。&lt;/p&gt;    &lt;p&gt;实际上，它们是使用了不同的参数进行三次贝塞尔插值计算的结果。所以我们先来复习一下贝塞尔插值：&lt;/p&gt;    &lt;p&gt;一个量（可以是任何矢量或者标量）从一个值到变化到另一个值，如果我们希望它按照一定时间平滑地过渡，就必须要对它进行插值。&lt;/p&gt;    &lt;p&gt;最基本的情况，我们认为这个变化是按照时间均匀进行的，这个时候，我们称其为线性插值。而实际上，线性插值不大能满足我们的需要，因此数学上出现了很多其它的插值算法，其中贝塞尔插值法是非常典型的一种。它根据一些变换中的控制点来决定值与时间的关系。&lt;/p&gt;    &lt;p&gt;K次贝塞尔插值算法需要k+1个控制点，最简单的一次贝塞尔插值就是线性插值，将时间表示为0到1的区间，一次贝塞尔插值公式是：&lt;/p&gt;    &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image007" border="0" alt="image007" src="http://images.cnblogs.com/cnblogs_com/winter-cn/201012/201012290019474843.png" width="452" height="21" /&gt;&lt;/p&gt;    &lt;p&gt;二次贝塞尔插值有3个控制点，相当于对P0和P1，P1和P2分别做贝塞尔插值，再对结果做一次贝塞尔插值计算&lt;/p&gt;    &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image008" border="0" alt="image008" src="http://images.cnblogs.com/cnblogs_com/winter-cn/201012/201012290019471462.png" width="422" height="23" /&gt;&lt;/p&gt;    &lt;p&gt;三次贝塞尔插值则是两次二次贝塞尔插值的结果在做一次贝塞尔插值：&lt;/p&gt;    &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image009" border="0" alt="image009" src="http://images.cnblogs.com/cnblogs_com/winter-cn/201012/201012290019476446.png" width="558" height="23" /&gt;&lt;/p&gt;    &lt;p&gt;回到我们的transition，我们要用到的就是三次贝塞尔插值算法了。&lt;/p&gt;    &lt;p&gt;把时间认为是0,1区间，待变换属性也认为是0,1区间，那么所有的控制函数都是三次贝塞尔函数：&lt;/p&gt;    &lt;p&gt;ease [0, 0] [0.25, 0.1] [0.25, 1.0] [1.0,1.0]&lt;/p&gt;    &lt;p&gt;linear [0, 0] [0.0, 0.0] [1.0, 1.0] [1.0,1.0]&lt;/p&gt;    &lt;p&gt;ease-in [0, 0] [0.42, 0] [1.0, 1.0] [1.0,1.0]&lt;/p&gt;    &lt;p&gt;ease-out [0, 0] [0, 0] [0.58, 1.0] [1.0,1.0]&lt;/p&gt;    &lt;p&gt;ease-in-out [0, 0] [0.42, 0] [0.58, 1.0] [1.0,1.0]&lt;/p&gt;    &lt;p&gt;cubic-bezier(x1,y1,x2,y2) [0, 0] [x1, y1] [x2, y2] [1.0,1.0]&lt;/p&gt;    &lt;p&gt;最后附上各函数图，请自行辨认：&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image010" border="0" alt="image010" src="http://images.cnblogs.com/cnblogs_com/winter-cn/201012/201012290019473381.jpg" width="120" height="125" /&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image011" border="0" alt="image011" src="http://images.cnblogs.com/cnblogs_com/winter-cn/201012/20101229001947316.jpg" width="127" height="128" /&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image012" border="0" alt="image012" src="http://images.cnblogs.com/cnblogs_com/winter-cn/201012/201012290019477252.jpg" width="118" height="118" /&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image013" border="0" alt="image013" src="http://images.cnblogs.com/cnblogs_com/winter-cn/201012/20101229001948217.jpg" width="124" height="115" /&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image014" border="0" alt="image014" src="http://images.cnblogs.com/cnblogs_com/winter-cn/201012/201012290019482693.jpg" width="120" height="116" /&gt;&lt;/p&gt;  &lt;p&gt;附上 transition演示: &lt;a href="http://files.cnblogs.com/winter-cn/transition.htm"&gt;/Files/winter-cn/transition.htm&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/winter-cn/aggbug/1919266.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/winter-cn/archive/2010/12/29/1919266.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/winter-cn/archive/2010/10/31/1865842.html</id><title type="text">那个我们爱的Silverlight</title><summary type="text">写这东西多少有点跟风的意思，不过最近的事还有大家的话多少让我回忆起一点对SL的旧感情。离开微软的时候我巴巴地主动把手里写的SL控件（Menu/MenuItem）邮件给SL组的人，其实那时候都已经决定要走了，然后还给他们留了私人邮箱，说以后有问题还可以找我，虽然到现在也没看他们用上。所以说说实话我从内心深处是希望SL好的。做为一个纯粹的技术人员，我看到的SL1.0是一个简单但是充满希望的产品，到了S...</summary><published>2010-10-31T15:43:00Z</published><updated>2010-10-31T15:43:00Z</updated><author><name>winter-cn</name><uri>http://www.cnblogs.com/winter-cn/</uri></author><link rel="alternate" href="http://www.cnblogs.com/winter-cn/archive/2010/10/31/1865842.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/winter-cn/archive/2010/10/31/1865842.html"/><content type="html">&lt;p&gt;写这东西多少有点跟风的意思，不过最近的事还有大家的话多少让我回忆起一点对SL的旧感情。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;离开微软的时候我巴巴地主动把手里写的SL控件（Menu/MenuItem）邮件给SL组的人，其实那时候都已经决定要走了，然后还给他们留了私人邮箱，说以后有问题还可以找我，虽然到现在也没看他们用上。所以说说实话我从内心深处是希望SL好的。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;做为一个纯粹的技术人员，我看到的SL1.0是一个简单但是充满希望的产品，到了SL2我看到的就是一个曲意攀附.net的商业化妥协产物。&lt;/p&gt;&#xD;
&lt;p&gt;好吧，技术人员还是谈技术吧。不知道大家记不记得SL1.0里面的这个用法：&lt;/p&gt;&#xD;
&lt;p&gt;item["ItemControl.source"]=//...&lt;/p&gt;&#xD;
&lt;p&gt;意思是ItemControl为其中的item附加了一个属性，当然因为JS的特性，ItemControl.source必须写成字符串的形式。提起这个是为了说，其实SL当年的志向并非一个UI framework或者浏览器插件那么简单，它是想做一个类似CLI的运行时。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Silverlight运行时最初设计的基础就是Dependency Object和Dependency Property（简称DO和DP），估计接触过Silverlight的弟兄们多少对这两个东西的存在应该是存疑的，估计也很少有人愿意去理解它们背后存在的道理。&lt;/p&gt;&#xD;
&lt;p&gt;其实相比JS用属性字符串名去访问属性，DO/DP是一个更加高效的动态语言运行时实现，你可以根据属性名去查找属性值，也直接根据DP对象去查找一个属性值，这比属性名快速的多。这个体系允许你在任何对象上添加任何属性，这是比较接近动态语言特性的。&amp;#8212;&amp;#8212;是的，这两个概念根本就不应该让程序员去知道和理解，这是语言运行时的实现方式。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;到了光芒万丈的Silverlight2，这个清晰的技术发展路线被扭曲了，微软的老板们只关心一个结果：开发者可以用C#开发Silverlight。当然也这也是无数程序员愿意看到。但是从来不曾有人追究到底如何去实现这件事。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;如果SL希望继续走它的"运行时"伟大梦想，它要做的事情就是在DO/DP体系上实现.net CLR，大家都知道在一个更加"动态"的运行时上实现一个更加不动态的运行时是可行的。另一条路，则是在CLR上实现DO/DP，这样做的直接后果是C#仍然跑在.net CLR上,但是必须用奇怪的语法去访问SL对象：&lt;/p&gt;&#xD;
&lt;p&gt;Control.getDependencyProperty(new DependencyProperty("width"))&lt;/p&gt;&#xD;
&lt;p&gt;但是我想是个人都知道前后两种方法哪个工作量更大。&lt;/p&gt;&#xD;
&lt;p&gt;而且那些奇怪的语法并非无法修补&amp;#8212;&amp;#8212;只要你愿意为每个属性写一个getter/setter&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;看过SL源码的人一定都知道SL团队最终做了怎样的选择，对于只有几十个控件SL而言，写几个getter/setter不过是一个程序员几天的工作量而已。我不曾参加SL团队，所以我不知道什么内幕消息，但是结果大家有目共睹&amp;#8212;&amp;#8212;SL团队最终选择了饮鸩止渴的做法。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;于是SL团队当然地以极高的速度完成了引入C#支持的任务，这对SL团队而言，我想也是极其重要的Achievement。坏处？坏处就是，当初那个做"运行时"的构想终结于此，还有就是以后每一个控件的每一个属性，都必须有一个DependencyProperty和一组getter/setter，这还没完，微软还必须维护SL中的这个精简版CLR&amp;#8212;&amp;#8212;事实上，此后很长一段时间里MVP和微软的人都在解释这个被阉割过的CLR跟.net CLR之间的关系。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;SL在UI编程模式的设计和抽象方面做的过于优秀，即使如今的HTML5，我也觉得远远不及，UI模型不是靠一两个Sample就能说清楚的，HTML5再好，也不过是多了几个标签&amp;#8212;&amp;#8212;说实话早该加了，只是W3C不够给力而已。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;看到IE9声明支持HTML5大家一副心慌的样子我笑了，IE什么时候支持过Silverlight了？如果不是同样打着MS的标志，恐怕大家根本就看不出SL这东西其实跟IE是一个公司的吧？就算微软的IE不去支持HTML5,估计结果也是IE9团队解散或者一帮人没事混日子，绝不可能出现IE支持Silverlight这一出戏。&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;所以说，搞死Silverlight的绝对不可能是HTML5,只能是Silverlight自己。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/winter-cn/aggbug/1865842.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/winter-cn/archive/2010/10/31/1865842.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/winter-cn/archive/2010/09/06/1819068.html</id><title type="text">我理想中的HTML和CSS</title><summary type="text">任何属性和内容都能以url的方式导入 比如 &amp;lt;p innerText="http://xxxxxx.com/content.txt%22%3E%3C/p&amp;gt;一个页面所有请求的资源可以被预先加载，可预测的资源在一个http请求中就获取到浏览器端style不再做为属性或者标签，而是做为一个页面描述渲染的文件导入&amp;#8212;&amp;#8212;对不同设备，可以由服务端决定返回什么样的Style S...</summary><published>2010-09-06T06:30:00Z</published><updated>2010-09-06T06:30:00Z</updated><author><name>winter-cn</name><uri>http://www.cnblogs.com/winter-cn/</uri></author><link rel="alternate" href="http://www.cnblogs.com/winter-cn/archive/2010/09/06/1819068.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/winter-cn/archive/2010/09/06/1819068.html"/><content type="html">&lt;p&gt;任何属性和内容都能以url的方式导入 比如 &amp;lt;p innerText="&lt;a href="http://xxxxxx.com/content.txt%22%3E%3C/p"&gt;http://xxxxxx.com/content.txt%22%3E%3C/p&lt;/a&gt;&amp;gt;&lt;/p&gt;&#xD;
&lt;p&gt;一个页面所有请求的资源可以被预先加载，可预测的资源在一个http请求中就获取到浏览器端&lt;/p&gt;&#xD;
&lt;p&gt;style不再做为属性或者标签，而是做为一个页面描述渲染的文件导入&amp;#8212;&amp;#8212;对不同设备，可以由服务端决定返回什么样的Style Sheet,即使给盲人用的语音浏览器，也能返回一个描述断句和重读之类的文件，而不是一成不变的CSS，这就实现了真正的表现和语义分离&lt;/p&gt;&#xD;
&lt;p&gt;Style Sheet可以嵌入脚本，有点类似expression但不是那么恶心的实现方式，Style Sheet也可以控制所有交互，比如Onclick，hover,mouseIn, mouseOut&lt;/p&gt;&#xD;
&lt;p&gt;不同的css计量单位可以互相运算 比如 width:300px-1cm+10% &lt;/p&gt;&#xD;
&lt;p&gt;Style Sheet可以控制标签的一切行为：甚至能用SVG来完全控制标签的形状&lt;/p&gt;&#xD;
&lt;p&gt;视频、音频只是Style Sheet级别的事情，&amp;lt;h1&amp;gt;乱世佳人&amp;lt;/h1&amp;gt;也能通过Style Sheet被解释成这部电影的视频播放窗口&lt;/p&gt;&#xD;
&lt;p&gt;&amp;lt;ball /&amp;gt;可以通过Style Sheet被显示成一个3D球体&lt;/p&gt;&#xD;
&lt;p&gt;Script不再以标签的方式嵌入HTML 而是独立的一个描述交互的文件 提供脚本中同步载入脚本的功能&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/winter-cn/aggbug/1819068.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/winter-cn/archive/2010/09/06/1819068.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/winter-cn/archive/2010/07/15/1777668.html</id><title type="text">(搬家文) c++引用深入探讨</title><summary type="text">(偶然翻起自己的旧博,忽然发现大三的时候写的这篇文章,仔细看看觉得写的还是那么回事,所以赶紧搭救出来)引用的声明: 基本格式：引用类型 &amp;amp;引用名=被引用对象&amp;amp;运算符：声明运算符&amp;amp; 跟取地址运算符&amp;amp;和位异或运算符&amp;amp;没有任何关系extern关键字:一般情况下 引用的声明必须指定被引用对象 唯一的例外是使用extern关键字const关键字:一般情况下 被引用对象...</summary><published>2010-07-14T16:08:00Z</published><updated>2010-07-14T16:08:00Z</updated><author><name>winter-cn</name><uri>http://www.cnblogs.com/winter-cn/</uri></author><link rel="alternate" href="http://www.cnblogs.com/winter-cn/archive/2010/07/15/1777668.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/winter-cn/archive/2010/07/15/1777668.html"/><content type="html">&lt;div  sizset="11" sizcache="0"&gt;&#xD;
&lt;p&gt;(偶然翻起自己的旧博,忽然发现大三的时候写的这篇文章,仔细看看觉得写的还是那么回事,所以赶紧搭救出来)&lt;/p&gt;&#xD;
&lt;p&gt;引用的声明:&amp;nbsp;&amp;nbsp; 基本格式：引用类型 &amp;amp;引用名=被引用对象&amp;nbsp;&lt;/p&gt;&#xD;
&lt;ol&gt;&lt;li&gt;&amp;amp;运算符：声明运算符&amp;amp; 跟取地址运算符&amp;amp;和位异或运算符&amp;amp;没有任何关系&lt;/li&gt;&lt;li&gt;extern关键字:一般情况下 引用的声明必须指定被引用对象 唯一的例外是使用extern关键字&lt;/li&gt;&lt;li&gt;const关键字:一般情况下 被引用对象必须是有效的左值对象&amp;nbsp;但是const关键字修饰的常引用类型允许被引用对象不是左值对象 &lt;/li&gt;&lt;/ol&gt;&#xD;
&lt;p&gt;引用的使用:引用可以被当作被引用对象的别名使用，单纯的引用是无意义的，引用主要应用于四个方面：&lt;/p&gt;&#xD;
&lt;ol&gt;&lt;li&gt;函数参数：可修改的实参，高效的复杂对象传递方式&lt;/li&gt;&lt;li&gt;函数返回值：不产生复制的返回值，返回左值类型的函数&lt;/li&gt;&lt;li&gt;运算符重载：为++ -- &amp;lt;&amp;lt; &amp;gt;&amp;gt;等运算符提供了更贴近原意的重载方式&lt;/li&gt;&lt;li&gt;多态：代替指针使用，实现抽象类的引用 &lt;/li&gt;&lt;/ol&gt;&#xD;
&lt;p&gt;引用的深入探讨：现在开始进入正题&lt;/p&gt;&#xD;
&lt;p&gt;1.引用占内存空间吗？&lt;/p&gt;&#xD;
&lt;p&gt;如果引用只是一个别名的话 他不应该占有内存空间　我用下面这段代码来查看&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="color: #0000ff"&gt;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;" onclick="cnblogs_code_show('e9fc4a94-6afc-4739-933b-78b9fcc3295e')"&gt;&lt;img id="code_img_opened_e9fc4a94-6afc-4739-933b-78b9fcc3295e"  onclick="cnblogs_code_hide('e9fc4a94-6afc-4739-933b-78b9fcc3295e',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt;&#xD;
&lt;div id="cnblogs_code_open_e9fc4a94-6afc-4739-933b-78b9fcc3295e"&gt;&#xD;
&lt;div&gt;&lt;!--&lt;br/ /&gt;&lt;br/ /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/ /&gt;http://www.CodeHighlighter.com/&lt;br/ /&gt;&lt;br/ /&gt;--&gt;&lt;span style="color: #000000"&gt;#include&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000"&gt;iostream&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;std;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;fa(){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;a[&lt;/span&gt;&lt;span style="color: #800080"&gt;4&lt;/span&gt;&lt;span style="color: #000000"&gt;];&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cout&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000"&gt;a&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000"&gt;endl;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;fb(){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;a[&lt;/span&gt;&lt;span style="color: #800080"&gt;4&lt;/span&gt;&lt;span style="color: #000000"&gt;];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000"&gt;b&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;a[&lt;/span&gt;&lt;span style="color: #800080"&gt;0&lt;/span&gt;&lt;span style="color: #000000"&gt;];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cout&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000"&gt;a&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000"&gt;endl;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fa();&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;fc(){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;a[&lt;/span&gt;&lt;span style="color: #800080"&gt;4&lt;/span&gt;&lt;span style="color: #000000"&gt;];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cout&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000"&gt;a&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000"&gt;endl;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fb();&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;main()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fc();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;getchar();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;return&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080"&gt;0&lt;/span&gt;&lt;span style="color: #000000"&gt;;&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="color: #0000ff"&gt;这段代码里　我用了三个嵌套的函数调用　这样　ｆａ　和ｆｃ的栈段就把ｆｂ夹在了中间　ｆｂ的栈段大小变化的话　会导致ｆｃ中ａ的地址偏移　但是并不是每个分配都会导致栈段增大的　所以应该先测试一下　确定ａ的合适大小　使得一旦声明变量 b的栈段就增大。&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="color: #0000ff"&gt;&lt;font color="#000000"&gt;把&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000"&gt;b&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;a[&lt;/span&gt;&lt;span style="color: #000000"&gt;0&lt;/span&gt;&lt;span style="color: #000000"&gt;];注释掉的话 可以看到fc中输出的地址变了 fb没有变 那么 引用b显然占据了内存空间 我的代码在g++中编译，结果也是g++的结果。&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="color: #0000ff"&gt;&lt;font color="#000000"&gt;&lt;span style="color: #000000"&gt;2.引用的值不可改变吗？&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="color: #0000ff"&gt;&lt;font color="#000000"&gt;&lt;span style="color: #000000"&gt;一个已经初始化的引用类型对象 其引用的对象不可能被合法的改变。&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="color: #0000ff"&gt;&lt;font color="#000000"&gt;&lt;span style="color: #000000"&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&lt;font color="#000000"&gt;&lt;span style="color: #000000"&gt;前面一段代码展示给我们 引用确实占据了内存空间 ，了进一步了解其本质，我们必须获得它的地址。&amp;amp;取地址操作符显然是无法做到的 几乎每个学c++的人都会尝试用这种办法去取引用类型的地址，但得到的都是被引用对象的地址。&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="color: #0000ff"&gt;&lt;font color="#000000"&gt;&lt;span style="color: #000000"&gt;还从前面的例子入手 fb中 a的地址没有改变&amp;nbsp; fa中a的地址改变 那么 int &amp;amp;b的分配应该在 二者之间 于是 最可能的位置就是a中的a[4]&amp;nbsp;&amp;nbsp; 但输出之后我发现a[4]不是，因为数组a是跟栈逆向分配的 之后我试了这样的代码&lt;br /&gt;void fb(){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int a[4];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int b=20;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cout&amp;lt;&amp;lt;a[-1]&amp;lt;&amp;lt;endl;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; fa();&lt;br /&gt;}&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;在我的编译器中 b跟a[-1]总是相等 于是 我把int b 替换成int &amp;amp;b=a[0]; ok 我发现它指向了一个貌似地址的东西。改变b的指向 发现a[-1]是随之变化的 现在 我几乎可以确定 a[-1]就是b了 再用一段这样的代码来检验&lt;br /&gt;void fb(){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int a[4]={1,2,3,4};&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int &amp;amp;b=a[0];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; a[-1]+=4;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cout&amp;lt;&amp;lt;b&amp;lt;&amp;lt;","&amp;lt;&amp;lt;a[0]&amp;lt;&amp;lt;endl;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; fa();&lt;br /&gt;}&lt;/p&gt;&#xD;
&lt;p&gt;引用真的是不可改变的吗？ 在这个例子中 我使b指向了a[1] 而不再是a[0]&lt;/p&gt;&#xD;
&lt;p&gt;3.引用和指针&lt;br /&gt;从上面的例子看出 引用的内部实现和指针并无两样。如果参考其他语言的思想的话 可以得到结论：引用就是指针常量。 在c++中 引用在语法上与指针有着明显的差异 但是 他们并没有本质不同 引用是c++中实现的一种限制比较严格的常量指针 它在参与任何运算之前自动解引用。&lt;/p&gt;&#xD;
&lt;p&gt;在使用中 推荐尽量用引用代替指针，因为引用是一种比指针更安全的类型 并且有更清晰的语义（当然指针也有适合的语义）&lt;/p&gt;&#xD;
&lt;p&gt;4.其他语言&lt;br /&gt;顺便一提，在C家的其他语言中 引用几乎被作为访问对象的唯一手段 &lt;/p&gt;&#xD;
&lt;p&gt;C++:有指针 所有运算符会解引用 所有对象不作为引用 传递参数和返回值时如果不希望复制 则必须将形参指定为引用类型&lt;br /&gt;C#:&amp;nbsp;unsafe模式有指针 除了=之外的操作符会解引用 所有对象作为引用 传递参数和返回值时如果希望复制 则必须显式clone&lt;br /&gt;Java:无指针 除了=之外的操作符会解引用 类似c#&lt;br /&gt;javascript:无指针但是可以变通 除了=之外的操作符会解引用&amp;nbsp;没有提供复制传递的方法(郁闷)&lt;/p&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/winter-cn/aggbug/1777668.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/winter-cn/archive/2010/07/15/1777668.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/winter-cn/archive/2010/07/07/1772567.html</id><title type="text">Visual Studio，不只是用来拖拖控件</title><summary type="text">一会用IDE，一会不用IDE，我可真烦人......And,继续标题党下去吧...... 我对拖控件这种标题党方式很有爱。言归正传，搞过一回命令行编译C#，这回咱们回来玩玩IDE，这一篇主要向大家讲一下VS项目的可定制能力，它并非是微软创造出来的一个专门给.net和Win32编程新手用的玩物，而是一个真正非常优秀的可扩展的IDE产品。你可以用它来管理项目和项目依赖关系，可以跟源码管理工具集成，编译...</summary><published>2010-07-06T17:33:00Z</published><updated>2010-07-06T17:33:00Z</updated><author><name>winter-cn</name><uri>http://www.cnblogs.com/winter-cn/</uri></author><link rel="alternate" href="http://www.cnblogs.com/winter-cn/archive/2010/07/07/1772567.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/winter-cn/archive/2010/07/07/1772567.html"/><content type="html">&lt;p&gt;一会用IDE，一会不用IDE，我可真烦人......&lt;/p&gt;&#xD;
&lt;p&gt;And,继续标题党下去吧...... 我对拖控件这种标题党方式很有爱。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;言归正传，搞过一回命令行编译C#，这回咱们回来玩玩IDE，这一篇主要向大家讲一下VS项目的可定制能力，它并非是微软创造出来的一个专门给.net和Win32编程新手用的玩物，而是一个真正非常优秀的可扩展的IDE产品。你可以用它来管理项目和项目依赖关系，可以跟源码管理工具集成，编译执行也不限于微软内置的集中开发语言，你甚至可以用它来开发Java。&lt;/p&gt;&#xD;
&lt;p&gt;这篇文章将会通过一个简单例子，来演示如何用VS来编译ilasm，这个应该也还是有些实际用处的，也方便喜欢研究ilasm的朋友。&lt;/p&gt;&#xD;
&lt;p&gt;首先第一步，我们建立一个C++空项目（没错，是C++空项目，对VS而言，VC++是一种自定义项目，它最接近我们的需求）。&lt;/p&gt;&#xD;
&lt;p&gt;接下来我们右键点这个新建的项目，选择&amp;#8220;工具生成顺序&amp;#8221;，然后把那一堆C++工具全都选掉，只留下自定义生成工具就行了。&lt;/p&gt;&#xD;
&lt;p&gt;好 这样我们的项目就编译不了C++了。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;接下来是重点，重新在VS中打开项目文件，然后右键点击&amp;#8220;自定义生成规则&amp;#8221;&lt;/p&gt;&#xD;
&lt;p&gt;然后我们新建一个规则文件，用来编译il文件。&lt;/p&gt;&#xD;
&lt;p&gt;新建一个规则文件之后新建规则，到这都很容易，就不用细说了。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/winter-cn/WindowsLiveWriter/VisualStudio_15B8/image_2.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/winter-cn/WindowsLiveWriter/VisualStudio_15B8/image_thumb.png" width="562" height="410" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;新建规则稍微有些复杂了，首先我们来参考一下ILASM的文档：&lt;a href="http://msdn.microsoft.com/zh-cn/library/496e4ekx(VS.80).aspx" target="_blank"&gt;http://msdn.microsoft.com/zh-cn/library/496e4ekx(VS.80).aspx&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;我这里只是为了演示，没有把太多的ilasm编译选项做成属性&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/winter-cn/WindowsLiveWriter/VisualStudio_15B8/image_4.png" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/winter-cn/WindowsLiveWriter/VisualStudio_15B8/image_thumb_1.png" width="603" height="580" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;填好后一路确定就行了。可以在项目中改变自定义属性来切换exe和dll：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/winter-cn/WindowsLiveWriter/VisualStudio_15B8/image_thumb_2.png" width="772" height="569" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;附上MSIL的helloworld以供大家验证：&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;" onclick="cnblogs_code_show('e7031fcf-8fed-4ff1-9104-297ccbcf073d')"&gt;&lt;img style="display: none" id="code_img_opened_e7031fcf-8fed-4ff1-9104-297ccbcf073d"  onclick="cnblogs_code_hide('e7031fcf-8fed-4ff1-9104-297ccbcf073d',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt;&#xD;
&lt;div id="cnblogs_code_open_e7031fcf-8fed-4ff1-9104-297ccbcf073d" &gt;&#xD;
&lt;div&gt;&lt;!--&lt;br/ /&gt;&lt;br/ /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/ /&gt;http://www.CodeHighlighter.com/&lt;br/ /&gt;&lt;br/ /&gt;--&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;&amp;nbsp;HelloWorld.il&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;&amp;nbsp;This&amp;nbsp;is&amp;nbsp;our&amp;nbsp;first&amp;nbsp;IL&amp;nbsp;program!&lt;/span&gt;&lt;span style="color: #008000"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;.assembly&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;extern&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;mscorlib&amp;nbsp;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;.assembly&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;HelloWorld&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;.ver&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080"&gt;1&lt;/span&gt;&lt;span style="color: #000000"&gt;:&lt;/span&gt;&lt;span style="color: #800080"&gt;0&lt;/span&gt;&lt;span style="color: #000000"&gt;:&lt;/span&gt;&lt;span style="color: #800080"&gt;1&lt;/span&gt;&lt;span style="color: #000000"&gt;:&lt;/span&gt;&lt;span style="color: #800080"&gt;0&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;}&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;.module&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;HelloWorld.exe&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;.method&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;privatescope&amp;nbsp;static&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;Main()&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;cil&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;managed&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;.maxstack&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800080"&gt;1&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;.entrypoint&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;ldstr&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #800000"&gt;Hello&amp;nbsp;World&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;call&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;[mscorlib]System.Console::WriteLine(&lt;/span&gt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&lt;span style="color: #000000"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;ret&lt;/span&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;附上整个项目压缩包：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://files.cnblogs.com/winter-cn/ilasm.rar" target="_blank"&gt;/Files/winter-cn/ilasm.rar&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/winter-cn/aggbug/1772567.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/winter-cn/archive/2010/07/07/1772567.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
