2007年4月29日星期日

恩杰二面归来

本来今天是个开心的日子:以来昨天晚上弄到两点的POS机终于可以跑sqlite-2.8.17了,另一方面,今天收到了人生第一个offer(尽管只是实习offer)。但是刚才去ask.com进行二面让我忧心忡忡。一扫前一段日子baidu和ebay面试的轻松和愉悦,可能这个更能让我清醒的认识到自己依然是那么土。

好了,说说面经吧。

到了ask首先让我感到意外的是居然有三个男的面我,和我第一次去遭受的草草了事的面试截然不同,这次似乎ask是有备而来的。

ask: 熟悉正则表达式么?
我: 不熟(因为我知道他要问脚本的东西)。

ask: 熟悉脚本语言么?
我: 不熟悉。只是知道有bash, perl, python,昨天刚刚买了learning perl, 准备一个星期入门。

ask: 说一下你在实验室的工作?你的实验室就是那个和cgogo。。。。?
我: 是的。。。。。。

ask: 你们在实验室主要用win还是unix?
我: unix。

ask: 那你怎么不熟悉脚本呢?
我: 我一般只是编编C/C++程序,对系统管理和一块并不熟所以就不太写脚本,而且一些应用脚本网上都有的down的所以一般只是copy而已。
(那三人面面相觑,这个时候坐我右边的一个人出去接电话了,少了一个。)

ask: 那说说C吧,你用的比较多的。C里面如何优化分配内存的?如何提高内存分配和回首的效率?不停的malloc和不停free会产生什么问题?
我: 发呆状...突然提到一个“缓冲”,但是感觉不是用在内存上的,于是说“不清楚”。

ask: 在linux下面如何调试多线程和多进程?如何根据core.dump提供的信息调试?
我: 暗自想“土了土了”,——不知道

ask: 熟悉linux kernel么?你用linux用到什么层次?
我: 不太熟悉,理论懂一点,没有太多实践。分析过一些IPC,写过测试,分析它们的效率。我一般就用到系统API这种层面,在往下就不太接触了。(又被鄙视,脚本这种日常的维护不会,而底层高端的开发也不懂,我自我调侃到)

ask: 那说说unix下面有哪几种IPC?
我: &……%*(流畅,难得啊,终于有流畅的了,多亏高级OS的课程作业)

ask: 如果有一堆url,它们指向一堆content,如何设计一种方法让它可以根据url找到对应的content?
我: hash.

ask: hash的算法有哪些?
我: (回答成冲突解决了,原来他说的hash算法就是hash function,我居然说不知道,但被鄙视了!该回家翻书了)

ask: 给你一个中序和后序遍历的结点序列,把它们还原成一棵树,在黑板上画。
我: (花了一分钟解决,还是觉得做得太慢,应该10秒钟解决才对,如果是考研那会的话估计肯定是秒杀的)

ask: *&……%¥(说了一下实习的相关细节)
我: No problems。

ask: 你希望我们最迟什么时候给你答复?
我: 5月10号左右吧...

终。


感想:
这次面试给我留下深刻的印象,因为太出丑了。我在回来的路上仔细想了下,觉得C/C++还是很有区别的。比如百度和ebay,它们都问了STL,而且baidu还问道了stl内部的实现机制和存在的危险,多线程不安全等以及多线程的调试。多线程这一块看来是一定要去实践一下的,这个可能是众多c/c++程序员必备的素质,特别是搞搜索。数据结构三个公司都问到了hash, 百度和ebay还问到了b+树。显然ask对于c/c++和unix开发的基本功要求远远高于baidu和ebay,后两个都是大公司可能更在意综合能力,比如ebay会全程English面你,知道和我聊到ebay和google这种过于复杂的问题才让我插几句Chinese。而ask这样相对的小公司可能更能培养技术上的一些东西,这是我个人的想法,当然没有拿到baidu的offer挺遗憾的,其实我在这个领域也只能算是入门,以后的路还长,要坚定的走下去,别再东搞搞java西弄弄c/c++了。把c和linux API弄熟是我今后一段日子的主要目标,就是通过我们寝室的那个金融搜索作为我训练实战的舞台。
最后打算利用一个星期的时间把Perl入门了,然后如果有幸能进去就在ask那边一边做一边深入Perl和网页分析等技术。

ebay offer到手

虽然工资很低,但是过去做的事情还是挺吸引我的。先是自贺一把,生平第一个offer嘛,哈哈!

Confidential

Intern Offer Letter实习邀请函


Dear 亲爱的 **

I’m writing to confirm an invitation for you to join internship of eBay China Development Center. The following are the key elements of your offer.

本信函是邀请您来亿贝软件工程(上海 )有限公司进行实习。具体情况如下:

* DEPARTMENT 实习部门

You will be offered as an intern in the department: PD

* DAILY ALLOWANCE 实习补贴

Your daily salary will be RMB*** (Before tax), plus lunch allowance of RMB** per day. Monthly housing allowance will be RMB*** only for those interns not coming from Shanghai or studying in Shanghai local universities. You will be responsible for your personal income tax.

* INTERNSHIP PERIOD 实习期间

Your internship will be from July 17th, 2007

* OTHER 其他

We anticipate that your internship will last for 8-12 months until you graduate from school. Your internship agreement, however, might be renewed once every 3-month based on the business needs, a new agreement shall be formulated.

You must guarantee that all the information and materials you provided are true; any falsity will result in immediate dismissal by eBay CDC.

我们预期您将在毕业之前一直在eBay CDC实习。在您报到之日我们将与您签实习协议,此协议每三个月续签一次。您应保证您提供的所有应聘信息和资料全都属实。如有不真实者,亿贝软件工程(上海)有限公司有权立即解除协议。



Your sincerely,

您真诚的

eBay China Development Center

亿贝软件工程(上海)有限公司

Date/日期:April 28th, 2007

2007年4月27日星期五

是全新交友方式,还是一夜情的温床?

男人女人总是一场演不完的游戏,但是抛开性和肉的赤裸裸,还剩下些什么?说白了也就这么一回事了,女人是虚荣的,特别是物质经济刺激下的今天,所以如果遇到了一个真心爱你的人,千万不要轻易放弃。希望以后带着老婆去“八点半”刺激一下。我和她如果褪去学生装的话都是非常耀眼的帅哥美女,呵呵。



是全新交友方式,还是一夜情的温床?
www.zjol.com.cn  2004年07月30日  浙江在线新闻网站

  即使没有了绚烂的华灯,杭州的夜也依旧闪耀着诱惑的光华……就像是位于杭州天目山路的八点半交友酒吧里一盏盏暧昧的红灯。

  这家名叫“八点半”的交友酒吧开张才几个月,却已成为杭州一些个性开放的前卫人群当下最红的去处。

  坊间种种传闻,让这家八点半交友酒吧蒙上了一层暧昧而神秘的面纱。这究竟是一家怎样的酒吧?抱着这样的疑问,记者在7月26日至7月28日,连续三天前往这家交友酒吧以窥其真实面目。

  火红的生意 陌生的男女

  7月26日晚上22点,记者一行5人前往八点半交友酒吧。“八点半交友酒吧”几个硕大的字在夜色中分外的醒目,而门口的车已经停得满满的。两个穿黑T恤的男子正来回奔跑着指挥陆续前来的车辆,“拐弯停到伊家鲜门口去,满了满了”,看到我们的车,他很没好气地叫着,与一般酒吧泊车员的殷勤截然不同。

   推开酒吧的大门,里面的喧嚣连同热闹扑面而来,与门外暗了一半路灯的天目山路形成强烈的对比。黑暗中,一盏盏红色的灯亮在每张桌子的上方,空气里有一种蒙昧不清的潮热在涌动。而舞台上握着一根钢管舞动的女子,配上电子屏幕上滚动的红字,正在诉说着“L先生想对圆圆小姐说认识你真好”的心迹,耳边阿杜那首《撕夜》被演绎得分外凄迷。

  酒吧里面的MM或吊带小背心、或单肩蝙蝠衫、或紧身衫小热裤、或半个后背裸露着的清凉着装。黑暗中,一个戴着墨镜、穿着露出臀沟的超低腰裤的前卫女子款款而来。一旁穿着花衬衫的引座服务生很熟络地和那女子打了个招呼,回头对记者说,“常客稳定、新客又多,所以下次要赶早来才有空位”;边说着,边艰难地给记者一行在门口安排了位子。

  由于是坐在大门口的位置,所以可以很清晰地看清每一个进出的人。记者发现来这里的女子大多衣着前卫、大胆,且年纪从22岁到40岁不等;而来的男子多以中年为主,也有不少事业有成的年轻小白领,所以出手大多还算大方。据酒吧的服务生介绍,一旦陌生女子欣然应约前来,男子必出手大方地任前来的女子点她要吃的酒水、点心、水果。

  因为是定位在陌生男女的交友会,来这家酒吧玩的人多目标明确,所以同来的绝大多数是同性朋友——不是清一色的男人,就是一群女孩子,绝少带着异性同来的。用这家酒吧门口卖羊肉串的贩子的话来说“别的酒吧一起来的都是有男有女,但是这家来的时候都是男的归男的,女的归女的,但走的时候却已是配好了对的”。

  交友酒吧催生各种欲望

  火红的生意、陌生的男女宾客是每一个到八点半交友酒吧最初的印象。这个地方能在其后的几个小时里催生出人的各种欲望。

  这家类似夜总会的交友酒吧与一般酒吧迥异的是,在每一张桌子上都有一部红色的电话机,上方悬着一盏红色的灯,灯上贴着老远就能看清的桌号。这是酒吧为来宾提供的一种全新的交友方式。只要你看到喜欢的异性,就可拿起听筒来、按照灯上黑的数字直接拨打对方桌上的电话。此外,来宾还可以用自己的手机发送交友信息至1778301,或者写在千纸鹤上交由DJ涛仔为你一诉衷肠。

  于是,借着酒吧里昏暗的灯光,那些寻找刺激的人的道德和准则就这样瓦解,因为看不到对方、不会被当面拒绝,所以电话邀约更助长了陌生男女相互结识的“勇气”。更何况酒吧还专门打印了一份《女(男)人打电话十大注意事项》,以此教初来此处的男人、女人如何用电话邀约陌生人。

  少许的酒,迷离的音乐,再加上这个定位为“交友”的酒吧因此就有了这样堂皇的氛围,更让由陌生人变情人在这里跨越了时间,幻化成一种极其简单的步骤。记者在这三天中就几次目睹那些先前陌生的男女在一个“勇敢”的电话邀约后,在酒精和音乐的催生下,他们用两个小时完成了由陌生人到情人的转变,更将人们惯常的道德准则轻易地抛弃。于是乎,就有了虽然进来的多是同性朋友,可离去的时候他们大都已有了相熟的异性朋友同去的场景。他们或举止亲昵地一同离去,或在座位上搂抱在一起,更有几个开放的男女,当众情不自禁地互舔起来,全然不顾旁人的尴尬。

  夜交往的暧昧游戏

  与记者同来的男性朋友试着拨了远处两个女孩的桌号,稍顷就有一个打扮入时的长发女子欣然前来应邀。

  微笑、落座,这是一个容貌姣好的女子,端着自己的酒杯,她穿得尚算得体,并非如先前几位的暴露、清凉。记者顺手拿起桌上的酒瓶要为她斟酒,结果她一把用手捂上了酒杯,示意服务生拿来新酒——原来,不喝别人的残酒是这里的规则,据说主要是提防别有用心的人在开的酒中下药。

  她自称“晨晨”,对于“做什么职业、哪里人”的提问,她充耳不闻;不仅如此,她也对记者一行的职业、年纪等情况不问一句……不问背景、不交换名片是这里最基本的游戏规则。

  “你要吃什么自己点”,同去的朋友很大方地放出豪言。晨晨虽然衣着简朴,但为人热情,记者才刚去了一趟洗手间,回来便见她已经手拿薯条往记者同去的男性朋友嘴里喂,并摆出一副很可人的姿态,倒是那位男士露出几分腼腆来。

  据晨晨自己说,她是这里的常客,可来得并不频繁,一周最多来这里两次。她说来这里的客人多是收入还算可以的小白领,孤单寂寞是她们来这里的主要原因,但享受被男人追捧、体会自己超然吸引力是来这里的女子共同的爱好,所以她们必然是悉心装扮、艳丽登场的。晨晨说完,故意向记者显了一下手上那个欧米茄手表,以显示她的经济实力和非三陪的身份。

  “我是个孤独的人,我来这里是等我命中的白马王子……因为早上要上班的缘故,我通常12点多就撤了。”晨晨一边说着,一边娇羞地看了一眼刚才放豪言请她自己点东西的朋友,“你不送我一下吗?”晨晨临走的时候对记者同去的朋友发出这样暧昧的邀请……

  据酒吧门口的几个常在那里候车的出租车司机说:“晚上我们常有接到那种先是男的要送女的回家,后来不是直接去了宾馆,就是一起下了车、去其中的一个人家里的。”

  看着酒吧里种种所谓“全新”的交往,闻着在酒精催生下、人们忘却道德和行为准则的暧昧空气,记者不禁纳闷,八点半交友酒吧这样的服务究竟是在为人们搭起一座新的沟通桥梁,还是在为一夜情提供放纵的温床,并加速毁灭人们濒临灭绝的爱情信念?



来源: 今日早报 作者: 文/本报记者 莫际芳 摄/本报记者 程瑞鑫

2007年4月26日星期四

[ZZ]谈谈Web Mining研究者掌握动态脚本语言的必要性

发信人: xuqingyang (网事随风), 信区: SearchEngineTech
标 题: 谈谈Web Mining研究者掌握动态脚本语言的必要性
发信站: 水木社区 (Fri Mar 23 17:58:30 2007), 站内

自己平时很喜欢在闲暇时学习一些新的计算机语言,它使我对计算机的兴趣不至于在书写各种申报材料和论文中完全泯灭。特别是在我把工作平台转向Linux后,学习各种开源语言更成为自己掌握在Linux下工作的一种必然选择,除了C/C++、JAVA、C#这些主流开发语言外,我尤其对Perl、Python和Ruby这样的动态脚本语言情有独衷,这里特别谈谈自己在学习它们的过程中的一些体会。

第一次接触Perl语言是自己在作WebMining研究时从CMU大学的著名网页数据集Web-KB开始的,它的代码里有一些Perl语言脚本,往往几行代码就能完成JAVA这样的开发语言几十行代码才能完成的任务。显然它比Bash这样的Linux中的shell脚本功能要强大得多。由于第一次读到Perl语言书写的代码,感觉真的像天书一样难懂,特别是那些到处可见的$、@、%等奇怪的符号。为了完全弄懂Web-KB的这些代码,我下决心开始学习Perl,结果没想到从此一发不可收,很快就成为Perl铁定的忠实拥户。下面是我总结的几点它最突出的优点:

1。实用:
它像编码世界里的"瑞士军刀",很多常用的处理方式特别作了很大的简化,让你用最少的代码量完成最多的功能。在JAVA语言里你需要首先声明各种变量,在程序执行前需要进行编译,在ERL语言里这些都去掉了,这大大简化了程序开发人员的开发效率。在JAVA程序里即使你只是打印一行"HelloWorld"也要先定义一个类,再定义一个static voidmain函数作为程序调用的入口,在PERL程序中这些全都不必了;再比如从网上下载网页在JAVA语言里至少要写上几行的代码,在Perl里只用一句就可以: use LWP::Simple; $html =
get('http://www.sina.com.cn');由于经常需要引入package,所以选择use而不是JAVA里的import,因为它比后者少敲三个键。由于编程时90%的情况是处理文本,它就把正则表达式作为语言的内置功能而不像JAVA那样首先需要import re;在所有动态脚本语言中它也是运行速度最快的。

2。第三方类库有集中的CPAN网站及其镜像站点统一管理:
这是另一个让JAVA语言开发者嫉妒的优势,浏览一下网页http://search.cpan.org/吧,它把十年来所有开源的第三方软件包分门别类地集中存储,如果你愿意,也可以把自己开发的觉的有价值的软件包与全世界共享。JAVA虽然有Jarkata这样的第三方类库,但绝大多数还是需要我们自己去寻找。

3。它是最像自然语言的计算机语言,不要忘记它的作者以前曾经是一个语言学家,如果你牢记这一点,那学习Perl语言便容易得多。我认为Perl语言也是目前我学到的所有语言中最具创新性的语言(它直接影响了Ruby),深深影响了以后各种新的语言的设计。

4。它是完全开源的语言,它的作者是计算机历史上大名鼎鼎的Larry Wall,他发明了patch命令和一个新闻组阅读器,但更主要的是他发明了Perl和CGI动态网页技术,他对Web的迅猛发展有直接的影响力。如果你想学习一门很多年后依然保持生命力的语言,那最保险的办法就是学习一门开源的语言,因为如果你去学习Delphi这样的商业语言,等到Borland公司一旦在商业市场上份额下降,那这种语言可能就完全风光不再。现在最热门的语言JAVA是Sun公司的宠儿,虽然Sun公司总裁声称在今年年底会完全公开JAVA源码,但显然这门语言的发展完全掌握在商业的运营模式中。

Perl语言当然有它的缺点:不像Python和Ruby一样易学;面向对象功能不是一开始就设计而是后来添加的;代码可读性较差,过于灵活。Larry Wall在2000年每年一度的开源大会上宣称开发新一代perl语言(即Perl 6)的计划正式发始启动,它将摆脱现在向下兼容的包袱,从内核上对语言进行重新设计,采纳当下各门语言的精华同时保留它最根本的特性。这是让无数perl爱好者兴奋到整夜难眠的事情,现在开发Perl6还没有实现,这中间台湾的唐宗汉(现变性后改为唐凤)起了力挽狂澜的作用,是我们华人在开源领域最骄傲的人物。(见http://www.linuxeden.com/doc/21782.html)我认为学习像perl这样的脚本语言对计算机专业的研究者来说尤其适合,因为它可以大大加快开发原型或验证算法的过程,特别是它对文本处理的支持至今是无与伦比的。以我个人经验来说,作Web Mining研究有一个很漂亮的想法很容易,但想得到实验数据的支持必须经过大量的Coding,它占用整个过程99%以上的时间(只关心发论文不在意伪造数据的除外)。如果用C++或JAVA语言来实现,你要花大量的时间用在Debug上面,但用Perl这样的快速开发语言,只花费十分之一的精力就能将其搞定,它免去了声明和编译(包括make过程),同时由于有很多现成的第三方软件包可以使用(在cpan里很容易找到Naive Bayes,Support Vector Machine这些机器学习工具),它的功能却一点也不逊色。特别的,由于它的代码量只有前者的几分甚至十几分之一,debug也相对容易得多。另外,使用perl语言最好结合Unix/Linux系统(虽然它在跨平台特性上一点不比JAVA差),这更能发挥它应有的作用。事实上在Linux系统下Perl是必备的工具(很多系统管理命令甚至带窗口的程序都是用它编写的,比如synaptic),你甚至无须去安装它。

Python是另一个非常好的选择,它的好处是代码可读性好,对面向对象支持得非常好,非常易学(一个下午的时间可以学会80%场合用到的20%命令),另外与C/C++和Java的互相调用也作得非常出色(所以它是一种更好的glue language),还有一个Perl语言没有的交互式编译器,它类似于以前苹果机上的Basic,你可以无须编写程序而直接在终端一行行边输入程序边看到结果,所以非常有利于快速开发。它的作者现在为Google工作,据说Google很多的代码都是用Python书写的。Python的名字来自国外非常流行的一个黑色幽默电影,放假时中央电影频道还专门介绍过它(下次我再次学习它时会先那部电影看一遍,找找感觉),开源世界的一大特色就是这种无比轻松的幽默而不是像微软产品包含的那种浓浓的商业气息。

Ruby现在由于Ruby on Rails的流行而成为亲的上升之星,有人甚至预言它是未来的JAVA,它从Perl语言和Ada语言吸取了很多东西,自己打算有空闲时间的时候好好学习它。它的发明人是个日本人,有些中国程序员便排斥这门优秀的语言,我当然对此不会在意的。据说敏捷开发之父非常推崇这种语言,因为它是比JAVA还要纯的面向对象语言,像字符串和数学这些都作为对象处理,可以直接调用各种方法。可以想见,它也是速度最慢的动态脚本语言。但很多情况下这一点并不重要。

2007年4月24日星期二

[ZZ]C++内存分配


一、内存基本构成
可编程内存在基本上分为这样的几大部分:静态存储区、堆区和栈区。他们的功能不同,对他们使用方式也就不同。
静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。
栈区:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
堆区:亦称动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或delete释放内存。动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。但是,良好的编程习惯是:如果某动态内存不再使用,需要将其释放掉,否则,我们认为发生了内存泄漏现象。

二、三者之间的区别
我们通过代码段来看看对这样的三部分内存需要怎样的操作和不同,以及应该注意怎样的地方。
例一:静态存储区与栈区

char* p = “Hello World1”;

char a[] = “Hello World2”;

p[2] = ‘A’;

a[2] = ‘A’;

char* p1 = “Hello World1;”


这个程序是有错误的,错误发生在p[2] = ‘A’这行代码处,为什么呢,是变量p和变量数组a都存在于栈区的(任何临时变量都是处于栈区的,包括在main()函数中定义的变量)。但是,数据 “Hello World1”和数据“Hello World2”是存储于不同的区域的。

因为数据“Hello World2”存在于数组中,所以,此数据存储于栈区,对它修改是没有任何问题的。因为指针变量p仅仅能够存储某个存储空间的地址,数据“Hello World1”为字符串常量,所以存储在静态存储区。虽然通过p[2]可以访问到静态存储区中的第三个数据单元,即字符‘l’所在的存储的单元。但是因为数据“Hello World1”为字符串常量,不可以改变,所以在程序运行时,会报告内存错误。并且,如果此时对p和p1输出的时候会发现p和p1里面保存的地址是完全相同的。换句话说,在数据区只保留一份相同的数据(见图1-1)。

例二:栈区与堆区

char* f1()

{

char* p = NULL;

char a;

p = &a;

return p;

}

char* f2()

{

char* p = NULL:

p =(char*) new char[4];

return p;

}

这两个函数都是将某个存储空间的地址返回,二者有何区别呢?f1()函数虽然返回的是一个存储空间,但是此空间为临时空间。也就是说,此空间只有短暂的生命周期,它的生命周期在函数f1()调用结束时,也就失去了它的生命价值,即:此空间被释放掉。所以,当调用f1()函数时,如果程序中有下面的语句:



char* p ;

p = f1();

*p = ‘a’;

此时,编译并不会报告错误,但是在程序运行时,会发生异常错误。因为,你对不应该操作的内存(即,已经释放掉的存储空间)进行了操作。但是,相比之下, f2()函数不会有任何问题。因为,new这个命令是在堆中申请存储空间,一旦申请成功,除非你将其delete或者程序终结,这块内存将一直存在。也可以这样理解,堆内存是共享单元,能够被多个函数共同访问。如果你需要有多个数据返回却苦无办法,堆内存将是一个很好的选择。但是一定要避免下面的事情发生:



void f()

{



char * p;

p = (char*)new char[100];



}


这个程序做了一件很无意义并且会带来很大危害的事情。因为,虽然申请了堆内存,p保存了堆内存的首地址。但是,此变量是临时变量,当函数调用结束时p变量消失。也就是说,再也没有变量存储这块堆内存的首地址,我们将永远无法再使用那块堆内存了。但是,这块堆内存却一直标识被你所使用(因为没有到程序结束,你也没有将其delete,所以这块堆内存一直被标识拥有者是当前您的程序),进而其他进程或程序无法使用。我们将这种不道德的“流氓行为”(我们不用,却也不让别人使用)称为内存泄漏。这是我们C++程序员的大忌!!请大家一定要避免这件事情的发生。

总之,对于堆区、栈区和静态存储区它们之间最大的不同在于,栈的生命周期很短暂。但是堆区和静态存储区的生命周期相当于与程序的生命同时存在(如果您不在程序运行中间将堆内存delete的话),我们将这种变量或数据成为全局变量或数据。但是,对于堆区的内存空间使用更加灵活,因为它允许你在不需要它的时候,随时将它释放掉,而静态存储区将一直存在于程序的整个生命周期中。
我们此专题仅仅是简要的分析了内存基本构成以及使用它们时需要注意的问题。对内存的分析和讨论将一直贯穿于我们以后所有的专题,这也就是为什么把它作为第一讲的原因。

Scott Meyers: 我之C++拍案惊奇

我之C++拍案惊奇

在本系列第五也是最后一篇文章里,我将选出让自己拍案惊奇、豁然开朗的五个时刻。

如果你从事某项工作的时间足够长,必然有几次在疑窦丛生的同时,忽感豁然开朗的经历(如果没有过,那你肯定是入错行了)。每当这些时刻来临的时候,我都惊得呆了,禁不住大口吸气;好像原来只见黑白二色,突然穿越了时空,来到一个五光十色的世界。最后我慢慢回过味来,面带微笑。如此时刻让人激动。疑窦烟消云散,洞明取代了它的位置。

这样的事情在1978年就出现过一次。经过长期的煎熬,有一天我突然明白了指针的工作原理——如果说软件学习之路上也有成年礼的话,那它就是吧。但我那时还在使用Pascal编程,因此不能将它列入这个和C++相关的名单。现在公开我的选择吧:


认识到C++中特殊成员函数可以声明为private[注释1],1988年。和很多朋友一样,那时我正在自学C++。某天,刚毕业的同事John Shewchuk跑到我的办公室问我,“如果得到一个不可拷贝对象?”在场的有好几个人,但都不知如何回答。我们知道,如果不定义拷贝构造函数和拷贝赋值操作符,那么编译器会自动加入,最后得到的对象是可拷贝的。若要阻止编译器自动生成,我们就必须手工定义,但这样一来,对象还是可拷贝的。就像Grinch[注释2]一样,我们个个迷惑不解,没有人能找到解决办法。

后来(可能是当天或第二天,我记不清了),John宣称自己有了解决办法:将拷贝构造函数声明为private就搞定了。现在看来,这个问题是多么简单啊!但当时对于我们来说,不蒂于发现了新大陆;这是我们对C++知识融会贯通的重要一步。三年后,我出《Effective C++》第一版时,将这个简单的发现供奉在一个独立的条款(不到一页,大概是这本书中最短的条款)里。再后来,我愈加意识到这个发现的重要性,因此在《Effective C++》的后面两版中都写了进去。1988年,我不觉得这种用private阻止编译器隐式生成函数的方法显而易见;现在是2006年,我还是这么认为。


理解Barton 和Nackman在单位分析(译者注:Dimensional Analysis。更学术化的叫法是量纲分析)法中提出的无类型模板参数(non-type template parameters)的用法,1995年。1988年5月,我在《IEEE Software》上读到Robert F. Cmelik和Narain H. Gehani合著的一篇文章——《Dimensional Analysis with C++》。他们提出了一种在物理单位(如长度、速度和时间等)的计算过程中检测单位错误的方法。比如,用长度除以时间,再将结果和一个速度量比较是正确的,但和加速度量(它由长度除以时间的平方得来)比较就错了。Cmelik和Gehani提出,可以将单位信息存储到对象中,然后在运行时进行错误检测。这种方法将使对象变大,而且耗费运行时间。我觉得应该有更好的办法,但折腾再三也没有结果,后来就不了了之。

John J. Barton和Lee R. Nackman在他们1994年出版的《Scientific and Engineering C++》(Addison-Wesley出版社)中提出了一个很好的单位问题解决方案。不过,虽然我当时也拿到了这本书,却没有注意到该项成果——老实说,这本书写得太糟糕了点,我开了个头就扔到一边。直到1995年,我通读了Barton和Nackman发表在《C++ Report》上的专栏文章,他们这次用通俗易懂的语言描述了自己的方案。结果给我留下了三方面深刻印象。第一,它涵盖了单位的所有可能组合,而不仅仅以命名为依据的组合,因为命名是不完全的。例如,我们将长度除以时间的结果命名为速度,还将压力除以长度的平方的结果命名为压强,但却没有给长度乘以时间的平方再除以角速度的立方的结果一个名份。至少我不知道。即便计算中产生了迄今为止还用不到的单位组合,B&N方案也会确保单位分析的正确性。

第二是B&N方案的运行时消耗:没有。对象没有变大,程序也没有变慢。因此可以说B&N方案是无本而万利[注释3] 。这才是我真正感兴趣的组合方式。

不过最让连连称奇的,还是他们对无类型模板参数(代表各种基本单位的指数式)及其上算术指令(计算结果单位类型)的使用 [注释4]。这样,他们不仅解决了多年前搞得我兴趣索然的实际问题,而且使用的还是一项C++特性(即无类型模板参数。它在那以前引发了我无穷的好奇心)。

直到今天,我还为Barton和Nackman的成果激动。原本打算将他们在《C++ Report》上的文章列入我的“C++历史上最重要文献”名单,但后来我发现它影响甚微——很少有人像我那样认为他们的成果具有重大意义。现在,我觉得自己有点可耻,因为我只顾自己满足,却没有将好东西与更多人分享。


理解Visitor模式的涵义,1996或1997年。命名恰当,是软件工程的一个基本原则。这儿就有一个例子,充分说明了糟糕的命名会多么折磨人。我没觉得Visitor模式的设计机理有什么特别问题,但就是一直弄不明白它的意义。我无法将支离破碎的认识融会贯通。直到后来有一天,我终于明白:Visitor模式和“访问”毫无关系。其实,它是一种体系设计方法——要求引入新的虚拟行为函数时不必改变原体系的结构。抓住这点后,我一下就理解了这个模式的含义。但其命名于我造成了巨大理解障碍,甚至看了《Design Patterns》(http://www.artima.com/cppsource/top_cpp_books.html#dp)如下的描述后:

Visitor使你不用改变行为操作的元素的类,就可以定义新行为。

这个解释清楚而直接,现在看来很好理解,但我当时就是盯住了模式的名字,总觉得“Visitor”应该和“访问”、“遍历”啥的发生点关系。

出现这种结果,我想有两个可能原因。一是我死心眼,见识短浅,鼠目寸光。再有就可能是这个名字选得过于随意。如果名字本身指的张三,而使用文档上说的却是李四,那么至少一些人——比较执拗的那种——肯定要搞糊涂了。我倾向于后一种解释。


理解“remove”为什么实际上并没有删除任何东西,1998年?我与STL的remove算法相遇得不是时候。当我期望Visitor设计模式访问个啥的时候,我也认定remove算法就应该删除某个东西。但结果让我非常震惊,我发现在容器上执行remove[注释5]时,容器内元素数目根本不会改变!我有一种被出卖的感觉——我是正儿八经要求删除啊!骗子!谎言!无聊的广告!

后来我读到一篇文章——可能是Andrew Koenig的《C++ Containers are Not Their Elements》(发表于《C++ Report》1998年11-12月刊)——它才让我明白STL内部的真相:算法不能改变容器内元素的数目,因为算法根本不知道容器的类型。容器还可能是一个数组呢,显然数组的大小是不可改变的[注释6]。自然,算法应该和容器彼此独立,互不影响。我认识到,“remove”不会改变容器内元素数目,因为它不能。直到那时,我才算真正理解了STL的内部结构,知道迭代器(iterator)虽然通常由容器成员函数提供,但就像容器和算法一样,其实它也是完全独立的实体。后来,我把这篇文章读了很多次。类似上面的解释,可能别人都说过很多回了,但别怪我鹦鹉学舌,这可是我第一次真正理解remove。

自此以后,我就能与remove和睦相处了。再后来,当发现remove不仅将份内事情做得很好,而且效率超过绝大多数程序员自己编写的循环(remove的运行时间是线性的,而普通循环是二次的)时,我甚至对它有点另眼相看了。虽然我仍然不太喜欢这个命名,但也说不清到底哪个名字既能准确描述其行为,又便于记忆。


理解Boost库里shared_ptr的deleter如何工作,2004年。Boost的引用计数智能指针shared_ptr很有趣——你可以向其构造器传递一个函数或者仿函数(function object,或functor),当引用计数归零的时候,它将在被引用对象上调用删除器(deleter)[译注7]。乍一看,似乎没啥了不起啊,但请看代码:



template

class shared_ptr {

public:

template

explicit shared_ptr(U* ptr, D deleter);

...

};


注意shared_ptr必然在析构时调用类型为D的删除器,然而它根本不知道D为何物。这个对象不能包含类型为D的数据成员,也不能指向类型为D的对象,因为声明其数据成员时,D对它而言还是未知的。那么,shared_ptr对象如何跟踪删除器(它在构造阶段传入;当T对象将被销毁时,还得使用它)呢?更通俗地说,构造器如何将未知类型的信息传递给它正在构造的对象,而这个对象本身对信息类型完全无知?

答案很简单:让此对象包含一个指向已知类型基类的指针(Boost叫它sp_counted_base),然后让构造器以D为参数实例化一个派生于上述基类的模板(Boost中叫sp_counted_impl_p和sp_counted_impl_pd),最后用声明于基类、实现于派生类的虚函数(Boost中使用dispose)去调用删除器。用图表示更为直观:


完全明白了——只要你看过这个图[译注8、9]。而且,看过此图后,我想你马上就会意识到它可以应用在很多领域;它为模板设计拓宽了思路,比如,模板化类使用很少的模板参数(例如shared_ptr只有一个),就可以跟踪无限个先前未知类型的信息)。当我想到这些的时候,我禁不住面露赞许的微笑,难抑钦佩之情[译注10]。


好了,文章结束,这就是我的5×5系列的末篇。简单总结一下本系列全部文章:C++历史上最重要的图书、文献、软件、人物,最后是对我来说最难以忘怀的五个神奇时刻。我还将再次和大家讨论这类有趣的话题,不过那至少应该是又一个18年后了。


注释:

1. 可能不一定非叫“特殊”成员函数不可——不过《Standard》如此称呼——具体包括缺省构造器、拷贝构造器、拷贝赋值操作符和析构函数。之所以“特殊”,是因为如果使用了它们而又未显式声明,编译器一般会隐式生成。

2. “Grinch两腿冰冷站在雪地里,想了又想:‘怎么会这样呢?’”参见Dr. Seuss的《Grinch如何偷走圣诞节》(Random House出版社,1957年)。不过在网上也能看到哦(http://www.kraftmstr.com/christmas/books/grinch.html,别告诉Random House)。

3. 我指的是不消耗更多运行时时间。他们大量使用了模板,当然会增加编译时间。

4. 你将两个数相乘时,就等于增加了指数次数,没忘记吧?

5. 我指的是STL的通用算法,而非list类的成员函数。

6. 重新分配内存不能算,不是所有的数组都是动态分配的。

7. 不要吃惊,TR1的shared_ptr就是以Boost的shared_ptr为基础并提供了相同功能。我正讨论的是Boost的shared_ptr,因为它有一个实现,我们这里说的也是实现问题。TR1仅仅是一个规范,如果你书生意气,问我TR1里讲的东西如何实现,那就没意思了。

8. 更准确地说,你以前应该看到过相关解释。譬如我,我得到的解释(我经常要别人给我讲解C++方面的问题)来自于Usenet新闻组的一个免费讨论(http://tinyurl.com/r66ql)。

9.我相信它也是外部多态(External Polymorphism,http://www.cs.wustl.edu/~schmidt/PDF/External-Polymorphism.pdf)设计模式的一个应用。自从我读过Chris Cleeland 和Douglas C. Schmidt于1998年9月发表在《C++ Report》上的有关此模式的文章后,我就喜欢上它了。不过直到现在,我仍然没看到这个模式的广泛应用。

10. 我觉得有两点需要说明。第一,它是Boost中大量成功创新的一个典范,Boost的创新性正是我将其列入“最重要C++软件”的原因之一。第二,很可惜的是,Boost中的这些创新未被整理并在C++社区广泛传播,很多有趣的东西,都掩藏在Boost库的盖子下不为人知。

9.我相信它也是外部多态(External Polymorphism,http://www.cs.wustl.edu/~schmidt/PDF/External-Polymorphism.pdf)设计模式的一个应用。自从我读过Chris Cleeland 和Douglas C. Schmidt于1998年9月发表在《C++ Report》上的有关此模式的文章后,我就喜欢上它了。不过直到现在,我仍然没看到这个模式的广泛应用。

10. 我觉得有两点需要说明。第一,它是Boost中大量成功创新的一个典范,Boost的创新性正是我将其列入“最重要C++软件”的原因之一。第二,很可惜的是,Boost中的这些创新未被整理并在C++社区广泛传播,很多有趣的东西,都掩藏在Boost库的盖子下不为人知。

Scott Meyers: C++历史上最重要人物

C++历史上最重要人物

C++是一门技术,而其背后支持它的是人——这些人发明、完善、繁荣和应用技术。本周,我将介绍我心目中最重要的五位C++大师。

本周名单上的这些人都拥有巨大的公众影响力。这些“公众人物”(抱歉,都是男性,不过我也没办法)能对很多人产生直接影响。受你影响的人越多,你自然就越重要。

不过,在系列的开篇文章里我也提到过,我是一个C++局外人。可能还有一些在台前幕后对C++产生了重要影响的人物不为我知。Stroustrup或许只是为众多技术工作者代言,标准委员也可能是替代一些不愿抛头露面团体做前台表演。如果是这样,那他们还真的达到目的了:我不知道他们。当然也就不会出现在我的名单上。

另外,我对入选者还有两点要求:(1)应该长期从事C++工作;(2)现在仍在为C++工作。重要的人很多,但最重要的人应该是长期而持续为C++做出贡献,并且直到现在仍在努力。

好了,现在公布我的名单,以较之新闻组文章更正式发表物(当然,这肯定比他们实际开始C++工作的时间晚,因为任何成果在产生影响力前都需要一个周期)的时间为序。在此,我仍然限制为五个名额,没有并列,也没有荣誉奖。因为我这是品活人而不是评静物,难度很大啊。规矩就是规矩,我必须要坚持。


Bjarne Stroustrup(http://www.research.att.com/~bs/homepage.html),1985年至今。嗯,怎么说呢,他是C++发明人,并编写了第一个编译器,还撰写了大量文章和图书(参见http://www.research.att.com/~bs/papers.html),积极参与C++的普及与标准化工作,并且一直持续到今天(如最近的SELLs(http://lcsd05.cs.tamu.edu/papers/stroustrup.pdf)和STAPL(http://parasol.tamu.edu/groups/rwergergroup/research/stapl/,合作者)研究项目)。本来,Stroustrup很多年前就可以退休了,躺在无数的赞誉声里懒洋洋地晒太阳。但他却选择了继续他30年前就开始的研究工作,这是对现代C++(最开始叫“C with Classes”)发展的巨大贡献。尽管我无意评比名单入选人孰轻孰重,但很难想象C++领域里还有谁比发明、最初实现,然后又引导它融入现代软件开发的人更为重要。



Andrew Koenig(http://www.acceleratedcpp.com/authors/koenig/),1988年至今。Andrew Koenig应该是绝无仅有、即便没有撰写任何C++文章和图书也能进入这个名单的人。他是一位真正的C++内部权威,这一点因其写作历史而少为人知。他撰写过两本C++图书(与Barbara Moo合作。译者注:Moo为Koenig夫人)、一本C图书(我没打算用这个为他在C++上加分,但即使这样,他仍然……)和大量专栏文章(可参看其主页上的介绍)。

不过,Koenig最让我感到吃惊的是别人对他的提及率,特别是在C++标准化方面。他一直是引导公众认识STL重要性的践行者,并带领Alexander Stepanov(译者注:原Compaq首席科学家,现Adobe首席科学家,STL之父)将STL引入C++标准。

我已经记不清多少次听到或读到标准化委员会成员类似这样的话了:“我们也在考虑这个问题,但Andrew指出……”,“那的确是个问题,不过Andrew建议……”。事实上据我所知,Koenig是唯一被以其名字命名C++语言特性的人——在标准化工作中,人们发现命名空间相关的名字搜索规范有时会导致编译失败,比如:

std::cout << someObject;

Koenig对此提出了修改意见,这就是后来的“Koenig lookup”[注释1]。在标准中,此规范的官方名称是ADL(argument-dependent lookup),但《Standard》对其的详细描述,则是“[basic.lookup.koenig]”(如果你一定要知道出处,那我告诉你,3.4.2小节)。



Scott Meyers(http://www.aristeia.com/),1991年至今。同样,我必须拿出真凭实据说明我的重要性,而不是靠主观臆断。我会尽量保持客观,用大量事实证明我在C++世界留下了自己的印记——或许是一个伤痕。我写过3本书(像我妻子那样不算再版,如果算上再版,就是6本),发行量都很大。我还撰写过近50篇有关C++及其应用的专栏文章,并且这些年来,我还在不少会议和开发者大会上做过报告。我公布的很多技术规范也成了C++最佳编程实践的一部分[注释2],不少厂商提供的“lint-like”C++检测工具都支持我的规范,它们常常将我的规范作为指导意见。

显然,我在C++标准工作中也扮演了一个小角色。嗯,别误会(译者注:他并没有正式从事C++标准工作,具体可见http://blog.csdn.net/lxpbuaa/archive/2006/11/09/1375988.aspx中他对自己的说明),我的意思是至少有两份标准建议稿,都受到我的影响:“我们还需要进一步讨论这个问题,因为即便Scott Meyers也还没弄明白”(如TR1中有关增加智能指针的建议部分(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1450.html),可以在页面里搜索我的名字)。



Herb Sutter(http://www.gotw.ca/),1997年至今。Sutter走上C++舞台不过10年时间,但其活跃程度几乎让人瞠目结舌。最早是自撰三本图书,和人合著一本。他发表过200多篇文章(绝大部分是独立作者,少量合作),特别让人吃惊的是,他同时是三个专栏的长期作者或合作者[注释3]。我也记不清他为C++标准化委员会提交过多少建议和其他文件了——我好像提到过他是该委员会主席吧?他还是《C++ Report》前任首席编辑,在各种会议和技术大会上做报告,他一直是我知道的对C++最具热情的鼓手。同时,面对性能敏感应用支持的日益紧迫,他还在多线程领域首倡抽象再构造,并为此寻找新方法——可能就是C++语言和库的未来扩展方向——以让开发者更加容易编写多线程代码。[注释4]



Andrei Alexandrescu(http://erdani.org/),1998年至今。是他的《Modern C++ Design》(http://www.artima.com/cppsource/top_cpp_books.html#mcppd)促成了我们模版思想的巨变,从此,Alexandrescu的名字也就和模版紧紧相连。甚至在一些场合下,他的名字就是模版的代名词,但这对他是不公平的。他对C++的贡献,远远不仅仅是尖括号的新用法(尽管就我所知,他是第一个描述“template template parameters”——即将模版作为参数在模版编程中使用——用法之第一人)。

即便抛开与Herb Sutter合著的《C++ Coding Standards》(Addison-Wesley, 2005),他发表的40多篇文章(http://erdani.org/publications/main.html)也充分展示了他在对象拷贝(object copying)、对齐约束(alignment constraint)、多线程编程、异常安全和搜索等领域的巨大贡献;他常常将性能提升看得比符合标准更为重要。以我看来,近几年来工作值得我们一直关注的,仅此Alexandrescu。绝大多数其他写作者和报告人(包括我)时常会奔回收割过的田野一遍遍巡视,以期捡到遗留的麦穗,而Alexandrescu却以其无人望其项背的速度,不断开荒,还在里面种上了新的庄稼[注释5]。



截至目前,我已经开出了C++历史上最重要的图书、文献、软件和人物名单。这些名单相对来说是比较客观的,但在此系列的最后一篇文章里,我想抛开客观,完全表达下自己的主观想法。下次,我将列出C++最重要的五个历史时刻——五个突然来临后,我对C++语言、工作方式及其应用的认识达到新高度的时刻。


注释:

1.简单来说,Koenig lookup指的是:如果函数的参数类型定义在名字空间内,那么函数被调用时,首先应该在此名字空间内搜索被调用函数,然后再是其他地方。比如调用“std::cout someObject”,应该首先在定义someObject的名字空间内搜索操作符“”的实现。像这样的操作符函数,如果在被它操作的类型的名字空间内也有定义,Koenig lookup就发挥作用了。

2.我这些年公布的大多数规范都已经成为C++社区的“基本常识”。我的主要贡献不是去自己发明发现这些规范,而是普及之。

3.如果你像我一样,也作过专栏作家,那么你就能更容易理解其工作量之浩繁。我已经很难做到一年六次跟踪那些值得阅读的东西,而Sutter众所周知是每月三次。

4.他还是Microsoft的C++/CLI首席架构师。将这点放在注释里说明,是因为我认为C++/CLI是C++的一个分支语言,而不是C++本身的一部分。直到现在,我仍然搞不清他哪来那么多时间同时开展这么多工作。

5.当然这并不是说所有他写的和提到的东西都是他首创的。尤其是他2001年开始读博士后,也常常会将学术上的研究成果传播到C++社区,例如无锁编程(lock-free program
ming)(http://erdani.org/publications/cuj-2004-10.pdf)。

Scott Meyers: C++历史上最重要的软件

C++历史上最重要的软件

在本系列的第三篇文章里,我将把视线转移到评选过去最重要的C++软件上来。

用C++编写软件,你需要工具的帮助。在我看来,这些工具曾经是(将来也是)有关C++的最重要软件。可以想见,曾经出现了不少用C++开发的重磅软件,它们促使很多人为了以后项目的开发选择了这门语言,但我不关心这些。这门语言最重要的软件应该是软件开发人群使用的最基本的东西:编译器和库。可能,C++是更为库编写而不是应用开发所设计的一门语言。

我选择的C++历史上最重要的五个软件如下,以诞生年份为序:

Cfront,AT&T的Bell实验室开发,1985-1993。Cfront是最早的C++编译器。它可是真正的编译器,不过生成的是C格式的目标码。因此将它认作C++到C代码的预处理器是很自然的。很难让人在调试时不做它想,因为至少在我1998年开始使用它时,仍然没有C++调试器。头发花白的前辈们当时使用C调试器,必须要对付那些让人精神崩溃的名字(比如,识别调试器里指向C++源代码中某个加法函数的__pl__1Aff)。

事实上,Cfront生成C目标码有两个好处。第一,可以非常容易将Cfront移植到新的平台,因为C编译器到处都是。这就促成了C++在各种环境里的快速传播。第二,使用者可以观察编译生成的代码,知道编译所做的工作。当大多数人还是C++新手的时候,通过揭示其工作过程,有助于消除大家对C++的神秘感。它也扮演某种保护伞的角色。不用担心C++用黑纱蒙住你的眼睛,因为它所做的任何事情都清清楚楚摆在那里(至少和从前机器生成的C代码一样清楚)。

在1990年前,Cfront不仅是个编译器,而且也成了事实上的语言标准。C++诞生于AT&T,Cfront来自AT&T的C++小组,因此无论Cfront干什么,自然是不会错的。长期以来,其他厂商的编译器紧跟Cfront,以致Cfront的bug都被原样复制。直到《Annotated C++ Reference Manual》(ARM)发布,Cfront的标准色彩才逐渐消退,特别是大家认识到要为Cfront加入异常处理机制需要付出巨大努力的时候。

Cfront的最后版本发布于1993年,但阴魂不散。Edison Design Group,一家专业生产最贴近C++标准的front-end编译器的商业公司,在2006年7月的文件里还指出它们的编译器兼容Cfront模式。我猜测仍然Cfront仍然在一些不支持本地C++编译器的嵌入式项目中发挥作用,当然仅仅是猜测。

GCC,GNU工程的杰作,1987至今。GNU很早就进入了C++商业领域,并且发布了第一个生成本地代码的编译器(相对Cfront的C++-C转换而言)。多年以来,GNU编译器成了跨平台应用开发的不二选择。事实上,它是一个交叉编译器,这也使它在嵌入式系统开发领域广受欢迎。GCC本身是一个支持多种front-end(包括C、C++和FORTRAN等)和针对各种平台的back-end工具的编译器平台,其C++版本就是广为人之的g++。

g++的早期推动人是Michael Tiemann。我不由得回忆起自己曾经提交了一份g++的bug报告,很快就得到了Tiemann的回应。他提供了新的g++文法,并请我据此重建编译器,看看我报告的问题是否解决了。我记得问题依然存在,但一个编译器的作者特意送你一个修改补丁并请安装试用,已经难能可贵了。顺便提及一下,Tiemann于1989年与人合伙创办了Cygnus Support,我相信Cygnus是历史上第一个提供免费软件的公司。据说早期的时候,Tiemann有时会躺在浴盆里召开Cygnus的会议。

g++是开源的,这样C++社区就可免费获得与C++标准一致的 front-end工具。但我从未听说哪个以g++代码为基础编写的开源工具(如Lint、重构工具等等)的解析能力能与g++比肩。有不少可以解析所有C++声明的工具(比如gccxml),但据我所知,没有哪个工具能同时解析声明和定义部分(特别是函数体)。因此尽管我于它没有个人使用经历,但我怀疑g++的front-end是否在完全开源上有所保留。这对于C++开发者来说是不幸的,因为尽管有很多工具可供使用,但其真正威力应该是解析[注释1]C++源代码的能力,这是一个难以逾越的障碍。

Visual C++,Microsoft出品,1992至今。VC++是C++成功的最大推动力之一,也是延缓C++进步的最大障碍之一。尽管Bjarne Stroustrup断言“没有人知道大多数C++开发者到底在干什么”[注释2],但我基本上不会怀疑如果我将这颗星球上所有C++开发者召集到一起,并要求为他们使用的编译器投票,我想大多数人都会提到VC++。仅就这点而言,VC++已经并将继续对C++产生重要影响。而且,Microsoft的旗舰产品(如操作系统、Office等)也完全或主要用C++编写,并用VC++编译。这也加重了VC++在C++世界的分量。该公司对C++的倚重促使它开发了很多工具和API来支持其应用,从而导致很多Windows开发人员也使用这门语言。到了90年代晚期,很多人(这让我震惊甚至恐惧)将C++叫做“Microsoft语言”[注释3]。VC++在C++领域占据了统治地位。对于大多数程序员而言,Visual C++就是C++。

不幸的是在Microsoft的C++实现里,标准的缺失持续了很多年。1998年前,这算不上一个问题,因为根本就不存在可以遵从的标准,其他编译器厂商也是各行其道。然而,VC6于1998年发布,此时距C++标准完成已近一年。与同类产品相比,VC6与C++标准差得最远。当然这在当时仍然不是一个十分的严重问题,因为很少有程序员马上使用C++标准里的最新特性。糟糕的是VC6一直维持到2002年(VC7发布),甚至VC7编译器本身也没有大的改变。在这些年里,对标准的支持,基本上都是以更新库(如STL)的形式实现,而我们很多人都觉得多年前就应该发布升级版本。2003年的VC7.1终于解决了大部分标准兼容问题,但在VC6至VC7.1的六年间,使用VC6的跨平台开发者必须因其缺陷付出艰苦努力,最典型的就是通过条件编译(也就意味着代码零乱)解决模板偏特化等问题。不过,很多开发者直到今天仍在使用VC6,他们也得继续感谢VC6小组大范围忽视标准兼容的决定。比如,新的版本在内存耗尽时不抛出异常,而直接返回空指针。

2003年后,VC++不再存在我认为相当严重的标准兼容性问题,我相信它现在的领导者非常重视标准兼容。然而,我在1998到2003这六年来经常接触的都是工作(至少就编程序而言)中并无特别困难的开发者,因此我理直气壮地决定将我对Microsoft的“警惕”保持到2008年——从他们发布一个“真正的”C++编译器起的六年。

The Standard Template Library,源自HP,1993年至今。像C++这类语言的标准库应该提供一系列常用容器和算法,这个说法并不会让人格外惊讶,但即便这样的作品也可能上这个榜。而STL对C++的贡献远非如此。它引入了容器和算法的设计架构,这样,仅仅通过迭代器交互就能实现无缝协作。它示范了如何用容器和迭代器替代数组和指针。此外,它还告诉用户如何扩展架构,允许引入新的容器、算法和迭代类型——它们可以像STL自有组件那样和任何符合STL标准的组件一起工作。所有这些都以效率为实现基础,不考虑经典的面向对象、基于继承的解决方案,而几乎完全依赖于模板技术。它还为C++引入了泛型编程。这一切的努力给我们带来了库和库框架设计思路上的转变,也满足了那些寻找便利的、可移植容器者的需求。我在《Effective STL》(Addison-Wesley, 2001)里写到,“我已经编程三十年,但我从未发现STL的比肩者”。现在已经超过了30年,我仍然没有发现。

Boost类库,诞生于1999年。这项选择似乎带点儿欺骗,因为Boost实际上不是一个类库,而是一个收容人们因各种目的和想法而设计实现的一系列库的组织。因此,Boost库在提供什么以及如何提供功能上似乎漫无目的。然而,Boost及其库对C++产生了重大影响,这种影响在未来可能更为明显。TR1中规定的14类新功能(其中13个已经写入C++0x草案)里,有10个[注释4]来源于Boost库使用者的建议。

Boost的影响并非偶然。它就是以充当那些可能最终被加入C++标准的库的实验床和推动者为目的而创立的。TR1对Boost的重视已经证明了它的成功,而且TR2很可能包纳Boost中更多功能。

如果在Google中搜索“C++ libraries”(不带引号),你会发现Boost排在头条。这是否意味着人们想到C++库,就会想到Boost呢?我想它至少说明了Boost与C++库的关系是多么密切吧。

当前,软件工具已经成为C++成功的关键因素,但归根结底,任何美好的东西都要人来创造。C++是如此,人类任何别的劳动也是如此。在下篇系列文章里,我将告诉你我认为谁是最重要的人——C++世界的巨人[注释5]。

注释:

1.所谓“解析”,我指的不仅仅是构建抽象语法树,还包括执行隐式模板实例化、解析重载函数调用等。也就是说包括解析和语义分析,不过很多C++工具的威力起点是语义分析的结果。人们常常将这整个过程叫做“解析”。

2.C++社区是如此庞大和复杂,以至于无法分析“大多数程序员”的行为。

3.“Unix语言”是Java,我不知道Apple语言应该是什么。

4. 它们是:reference wrappers、smart pointers、enhanced member pointer adapters (mem_fn)、enhanced binders (bind)、generalized Functors (function)、type traits、random numbers、tuples、fixed-size arrays和regular expressions。

5.每个人都知道巨人的力量,但我做名人研究的老婆却提醒我说,尽管巨人们都力量超群,但在他们的漫漫长路上,更多依靠的是艰辛努力而不是他们天生的神力。这就是他们前仆后继投身与奥林匹斯山主宰者(宙斯和他的仆从)斗争的原因。我将把判断C++世界里是否存在同样现象的问题留给你们,如果有,那么是谁或者说是什么扮演着奥运会选手的角色呢?

Scott Meyers: C++历史上最重要的文献

C++历史上最重要的文献

在本系列的上一篇文章里,我列出了我认为最重要的五本C++图书,但大量有关C++的重要文献并非来自图书。比如期刊、杂志、网络上的文章;博士论文、会议纪要;新闻组帖子;博客;标准化文档等很多很多。它们对C++的进步与繁荣作出了巨大贡献。我没有读全,甚至谈不上读了大多数,但作为C++的长期关注者,我还是阅读了很多这类文献。在本期里,我将评选C++历史上最重要的五部非图书类文献。和上期评选图书一样,我仍然将数量限制为五,尽管我没有写出过重要到能上这个榜的东西,但仍然将自己列入了候选队伍。以下文献按时间为序。

一个让我无可回避的逻辑范畴两难问题是:如果文献A的思想对C++直接影响很小,但文献B的作者读到了A,将这个思想引入了B并产生了巨大影响,那么到底哪个文献更重要,A(“发明者”)还是B(“繁荣者”)?我最终选择了B,并不是因为这种做法天然就正确,而是因为我不想花力气拼命追查下列文献作者的思想是否从别的文献继承而来[注释1]。反过来,我随便翻到C++语言规范的某页。大家知道,const member functions里的const是不彻底的:指针数据成员自动变为const,但指针所指的数据本身不会。借鉴这个规定,我假设公布在下面的名单里的文献重要,而忽略它们引用的基础物(以及我所不知的其他文献)。当然,从C++本身来说,这可能不是正确的做法,但易于实现,所以我也这么干了[注释2]。

在详细解说名单之前,我想请各位发发善心,允许我为《C++ Report》——曾经为C++作出了最重大贡献的期刊——说几句悼词(如果你不那么仁慈,就请直接跳过去阅读后面内容吧)。在其存在的大部分时期(1989-2000)里,《C++ Report》一直是C++推动者和鼓吹者纸张写作的乐园(在此期间,首倡电子写作的是Usenet新闻组comp.lang.c++,后来还有comp.std.c++和comp.lang.c++.moderated)。在《C++ Report》发表文章的人里,有些名字你可能听说过(比如我上期列出的“最重要的C++图书”的作者),更多的可能你就不知道了(譬如下面要提到的一些文献的作者,以及——算了,名单太长,简直没办法开始。我知道,如果开了头列出一些名字,那就暗示着未列出的人没列出的那么重要,这样一来我的麻烦就大了。所以干脆一个不提,但请相信我,《C++ Report》有生之年一直相当兴盛,它吸引了这个领域最好的写作群体——都是最有兴趣,也是最
有实力去写作的人)。《C++ Report》关门的时候,很多专栏作家投向了《C/C++ Users Journal》,但这个杂志从来没有像《C++ Report》那样吸引过我;现在,CUJ也停刊了。《C++ Report》留给像我这样整天胡说八道的老怪物们的,就只有面对时光飞逝的无奈哀叹了。

唠叨这么多,我感觉好点了,还是继续说我的最重要非图书类文献名单吧:

《Programming in C++, Rules and Recommendations》,作者是Ellemtel电信系统实验室的Mats Henricson和Erik Nyquist,1992年。在我90年代早期前后的一些文章里,我提到过当时很多程序员渴求如何驾驭C++威力方面的指导意见,他们最感兴趣的是告诉他们该做什么、不该做什么的编程引导手册。几乎在我的《Effective C++》尝试提供这方面指导的同时,Mats Henricson和Erik Nyquist在互联网上发布了他们写的编程手册。其实在此之前,这本手册就出来一段时间了,但因为是瑞典文,所以大大限制了它的传播。

Ellemtel版手册以技术性语言写成,容易阅读,因此二位作者声名远播、影响很大。不久,大家得知他们准备成书出版,此时我就有不祥预感(竞争于市场可能是件好事,但那时,我是这个市场上仅有的参与者。我真的很喜欢这本书册的风格[注释3])。我们对这本书满怀期待,转眼间时间过去了几年。1996年底,它终于面世了(《Industrial Strength C++》,Mats Henricson和Erik Nyquist, Prentice Hall, 1997),但那个时候,这本书的很多指导意见与同时代的编译器相比已经过时,它包含的很多信息在C++社区里已经广为人知,与4年前第一次的英文版相比,人们感觉它的作用已经大打折扣。我阅读了这本书,先是兴趣满怀,然后就有点伤感,因为我感觉到花费4年时光从互联网文档到成书,不仅它包含的技术信息失去了当年的光芒,写作本身也丧失了原有的精神。我估计原稿已经被无数次修改,以期符合评审者在各方面的要求。这就解释了它为什么花费了如此长时间才得以出版,为什么最后的成书如此平淡。

我想,作者和出版商对这本书寄予厚望,但事与愿违,不过这并不能削弱最初互联网版本的影响力。它一出来,C++程序员就一口咬了上去。它是C++最佳实践规范总结道路上的重要里程碑。

《Exception Handling: A False Sense of Security》,作者Tom Cargill,1994年发表于《C++ Report》11、12月刊。1994年,C++社区矫矜之气弥漫。当时,C++是很热门的语言,工作岗位充足,很多人认为C++无所不能。在此前几年里,这门语言里增加很多重要的特性,比如多继承、模板,以及稍晚点的异常。因为异常是新事物,《C++ Report》上就出现了很多讨论文章,凡是C++程序员出现的场合,大家都是三句话不离异常。很多文章反映了属于那个时代的狂热:“异常美妙之极,它们让错误处理变得简单。你需要做的所有事情就是去理解try、throw和catch。看我编写一个堆栈类吧,告诉你们C++有了异常处理后,将比过去酷多少。” Tom Cargill的文章(是他的长期专栏“C++Gadfly”——这是多年来最名副其实的专栏之一——里的一篇)拂去了我们脸上集体自满的微笑。仅仅用一句话,Cargill就说明了try、throw和catch对这个问题毫无帮助:

运用异常的真正难点在于如何以如下方式编写所有介于二者(thow和catch)之间的代码:任何异常都能从throw处安全到达处理它的地方,且不破坏传递路线上的其他程序部分。

这个专栏继续剖析了《C++ Report》上我刚才提到过的“异常美妙之极”系列专栏上的文章[注释4],最后以一个擂台(Cargill称之为“邀请”)结束:发布一个异常安全的堆栈类。这个挑战引来了潮水般的回应,但我认为,直到1997年,Herb Sutter发表的一篇文章才算真正有分量(后面会说到这个事情)。

我认为Tom Cargill的专栏文章不仅证明了我们对于异常想法的幼稚,而且也还了C++一个清白。在我们明白如何编写异常安全的代码时,Java这门可爱的新语言出现了(就我所知,现在是Ruby on Rails),曾经信誓旦旦的“我们天下第一”狂想再也没有回来过。

《Curiously Recurring Template Patterns》,Jim Coplien于1995年发表在《C++ Report》2月。这篇文章的意义不在于它的内容本身,而在于它给所述内容的命名。真是双重巧合啊,这篇文章来自于Coplien的专栏“The Column Without a Name”,而且他给文章起的名字也已经直接成了一个模式名:The Curiously Recurring Template Pattern (CRTP)[注释5]。这个模式本身是指将派生类作为参数在它自己的模板化基类里使用:

template\

class Base { ... };

class Derived: public Base\

{ ... };

很多人对模板的使用都超出了T容器的范围,最后往往皈依到了CRTP的设计思想。这时候,他们通常都会怀疑这样的代码是否可以通过编译,当发现可以通过编译(可能他们大吃了一惊)后,就很担心自己弄出这样的设计,是否是头脑痴呆的早期症状。就在这时,Coplien投稿了。更多有经验的同事会保证说:“不是啊,你没有精神病。从基类派生一个类,基类又在派生类的基础上模板化,不仅是合法的设计技术,而且它还有一个正式的名字呢:the Curiously Recurring emplate Pattern。”

《Using C++ Template Metaprograms》,作者Todd Veldhuizen,《C++ Report》1995年5月。此文见证了template metaprogramming (TMP)的第一次大规模出现热潮。这是一个重要的时期,但我完全错过了这条船。我清楚记得阅读这篇文章时我的想法:“好,这样你就可以用递归的实例化模板去模拟编译时的循环。你能通过模板特化去实现编译时的switch表达式。太好了!但你为什么要这样做?”哦,我说谎了。我当时真正的想法是:“但你如果这样做,你就是个疯子。”[注释6]

尽管C++社区并不缺乏追捧,再后来有关TMP的文章也在各种论坛上陆续出现,不过这不让我惊诧。我那时深信TMP是一门概念过于离奇、语法过于超前以至于没有立足点的技术。现在,我知道大多数人似乎也同意它在语法上的确让人感觉不适,概念上不说过于怪异,至少也偏离了主流思想,这让我得到了些许安慰。但很清楚,它获得的支持日益增多,已经成为每个库程序员技巧包里的重要工具。为了弥补Veldhuizen首次描述它时我对其重要性严重低估的过失,我在Effective C++》第三版的一个条款里尽我全力总结了这门技术及其用途。

《Exception-Safety in Generic Components》,作者David Abrahams。我能找到的最早的是发表在德国《Dagstuhl Castle》1998年4月27日到5月1日的《Proceedings of the International Seminar on Generic Programming》。不过我想在1997年中,相关文献可能就出现了,因为Herb Sutter发表在《C++ Report》(也许是别的杂志)1997年9月刊的一篇文章引用了David Abrahams论文里的内容。我也发现有对David Abrahams于1997年4月发表在Usenet上的文章(http://tinyurl.com/nk5vn)里内容的引用,不幸的是,这个链接已经实效。

现在,保证函数提供基本、强健和无抛出的三个异常安全办法已经广为人知。Herb Sutter传播了这些术语,并且写了很多相关的文章,但最早提出它们的是David Abrahams,我这么说的主要理由是Sutter已经很细心地承认过这一点[注释7]。一些重要文献初生于相当狭小的空间,但读者中间很多人有条件发挥广泛影响力(比如正在定义C++标准,或者负责标准库的实现),因此文献的影响力将会被大大提高。我想,这就是一个例子。

有趣的是,尽管Abrahams的文献启蒙了我们对奠定C++标准库规范基础的异常安全的理解,但C++标准里却未提及“basic guarantee”、“strong guarantee”或是“nothrowguarantee”。

注释:

1.因为传递环路问题(比如B的想法起源于A,但A的灵感来自于Z,Z又是受Y的影响……),实际情况比这还要糟糕。

2. const不彻底的这个理由可能和简化实现并不相干。其实考察const和指针结合时的常见规则,它就是一个很自然的结果。我们定义指针p为const,但这并不能限定*p也是const。在const member function里,*this是const,如果p是*this的一个指针成员,我们也不能确定*p就是const。

3.稍早一点,还有另一本C++书册类图书,即Thomas Plum与Dan Saks合著的《C++ Programming Guidelines》,1991年由Plum Hall出版,但它从未引起过大量关注。我很早就读过这本书,现在我又快速阅读了一遍,给它的结论是:嗯……相当无趣。

4.我是《C++ Report》的专栏作家,我记得那时候就在想,Cargill肯定瞄上了我,要我去写异常方面的东西。系统且有专业眼光地挑出同僚作品中的缺点,是我曾经经历过的最费心劳神的事情。我确信从此以后,自己不是发表作品前要再三检查的唯一专栏作家了。

5.正在布朗大学计算机科学系攻读博士学位的Andrei Alexandrescu曾经公开指出这个模式的名字应该被还以本色,比如“F-bounded polymorphism”,但很不幸,他的意见没有引起人们的注意。这件事引起了我的兴趣,因为我就在那儿获得了博士学位,不过我从未听说过“F-bounded polymorphism”。CRTP尽管是一个古老的名字,但仍然能打动我,因为它比“F-bounded XXX”显得更自然。

6.它可能对文献里第一个例子实现编译时冒泡排序没有什么用处。我对冒泡排序一直有相当病态的反感。不仅是因为这种排序算法几乎从来就不适用于我的工作,而且也几乎从来不值得在工作中考虑这种算法。哦,我离题了。

7.初时,这点还不完全清楚。Sutter在《C++ Report》1997年9月刊上发表的文章里并没有将“basic guarantee”和“strong guarantee”归功于Abrahams,但他提供并允许放在我的1999版《Effective C++》光盘的文章提到了Abrahams。我有十足把握公开说《C++ Report》发表的文章和Sutter提供给我的文章是不一样的。

Scott Meyers: C++历史上最重要的图书

Scott Meyers,C++顶级权威之一,为世界各地客户提供培训和咨询服务。出版有畅销的Effective C++系列图书(《Effective C++》、《More Effective C++》和《Effective STL》),设计了创新型的Effective C++ CD,Addison Wesley的Effective Software Development Series顾问编辑,The C++ Source (http://www.artima.com/cppsource/)咨询板块专家。布朗大学计算机科学博士,他的网站是www.aristeia.com。

1991年,我写作了《Effective C++》。在此之前,我已学习C++多年。坐下来撰写本文的同时,我相信我的C++学习历程始于1986年,现在是2006,正好是我学习C++20周年和写作第一本C++图书15周年纪念。不过,记忆里——至少在我的记忆里——不敢保证,似乎有历史记录证明过我实际于1988年开始接触C++。如果是这样的话,那么现在应该是我与C++的19周年纪念年。虽然这个数字比不得20那么完整,但仍然说明C++于我已是多年老友。今年里,无论作何考虑,我都觉得我不应该关注C++的未来,而是回想它的过去。目前,C++的未来是热门话题,比如备受关注的下一个版本语言规范(C++0x),临近最后定稿阶段,首版技术报告已经出炉,二版也正蓄势待发。但我现在想驻足过去,做点与众不同的事:分门别类评选C++历史上最重要的贡献。

首先要公布的是最重要的五本C++图书。公布之前,我想先罗嗦几句。这些C++领域最重要贡献是在我个人阅历和准则基础上评选的,是我的主观看法,这点自不待言。而不得不说的恰恰是我个人的阅历和评选准则。

你们很多人不得不承认:过去20年里,我从未开发过商业软件,更遑论用C++写这类程序。不,不光过去,将来我也不会。因此,我不但不是真正的C++开发人员,更说不上是C++崇拜者。如果一定要扯点关系的话,那就是我在1985-1993年上大学时,用C++写过一个研究用软件,很小,就几千行代码,我一个人开发,它很快就成了历史的尘埃。自从我十余年前专心作咨询师以来,我的C++编程仅限于玩乐,比如“让我们看看它如何工作”(有时候也“让我们看看它能让多少编译器崩溃”),通常,都是一个文件就可以容纳的程序。make?谁需要讨厌的make?我以C++为生,但不是写C++程序。

和语言标准化亲密接触,于我的生活也没多大干系,因为我从未成为C++标准委员会成员,未被列入委员会的邮件名单,也从来没有参加过任何标准工作会议。我对委员会内部工作的了解——包括对语言有重大影响的工作——都靠阅读他人的文章,或者从他们那听说。因此我对像我们知道的那样推动了C++发展的那些重大努力知之甚少,可能只有委员会内部的同志对这些努力感受最深。

上面说了,我既不用C++写软件,也没为语言规范贡献力量,那我到底在干嘛呢?你可能满怀疑窦。基本上可以这么讲,我就研究C++本身以及它的应用。尽我所能,通过图书、杂志、新闻组、邮件以及和开发者、标准化委员会成员面对面交流,加上我自己写程序做实验玩儿等,我收集了大量有关C++的资料,然后对它们做整理、分析,最后集中打包(如写书、在杂志上发表文章、作技术报告等)提供给真正使用这门语言的朋友们,比如你。你们的工作是使用C++这个工具,开发有用的软件;我的工作是搜集、整理能帮助你们更好使用这个工具的资料。

我希望将自己定位为局外观察员,既不像程序员那样日复一日辛苦劳作,也不愿为标准化工作的纷繁琐事殚精竭思,但我要对二者都保持熟悉。这一系列的文章,就是我这个自封的局外观察员对C++历史上最重大贡献的总结。

所谓“最重大”,我指的是这些贡献对C++开发人员产生了最重大的影响。我的名单上所列项,很多都发挥了直接性的影响,我们也直接感觉到了。比如广泛使用的编译器、库和读者众多的图书与文章,它们的影响力非常直接。另外一些的影响则是间接的——我是说它们首先对中间渠道产生直接或间接的影响,然后由中间渠道直接影响我们(哈,绕口令,惹你讨厌了吧?)——比如你稍后会看到的、被我列为最重要图书之一的《ISO C++ Standard》,对于开发人员,它的影响是间接的,但对编译和库编写者的影响却是直接的。

有些贡献的重要性非常明显,比如和标准有关的。其他的,通常则需要时间老人来验证它们的影响力。因此,在C++圈子里出现相对较晚的,与已经存在较长时间的相比,更不容易列入我的名单。比如我的图书名单里,最晚的只到2001年。这倒不是说在过去五年里出版的图书就没有价值,而是说,以我来看,这些图书还没有表现出我名单上所列图书更大的重要性。如果过些年再来问我,或许就会有所变动了。

五本最重要的C++图书

为了让这个名单(也包括后续文章中提到的其他名单)更有价值,我给自己定了两条原则。第一,只挑五本。哪怕多一本,让它共享这份荣誉的位子也没有,也没有为那些差不多靠边者准备优秀奖。五个位子,五本书。第二,我没有将自己的书排除在竞争行列之外。如果我要评判别人的书,当然也不能放过自己的。

这两个原则已经相当公平而严格了,因此我在其他方面就可以偷点懒:我不打算对名单上的图书按重要性从高到低排座次(其他几个名单也一样)。我的评判粒度是“在名单上”和“不在名单上”。每个名单里,我都以年代为序,本文的单子里,自然就是出版日期。

言归正传,下面揭晓我评选的过去出版的最重要的五本C++图书:

《The C++ Programming Language》,作者Bjarne Stroustrup,Addison-Wesley出版社。1986年首版,1991年再版,1997年第三版,2000年特别版。对于C++老人们来说,此书的首版是打开知识大门的钥匙。目前的版本已经膨胀到千页以上,增加了很多那时候还不存在的特性,如模板、异常、多继承等,不过未提及标准模板库;显然首版——也是我逐页阅读过的唯一版本——更易驯服,只有328页。身处80年代后半页的C++程序员,对这本书的完全旅行是必不可少的,它对早期的C++从业者和追梦人的重要影响,怎么评价都不过分。即使介绍C++的图书满天飞的现在,我仍然推荐专业开发人员阅读这本书(当前版本),因为我认为无论就C++本身,还是如何用好C++来说,它都是最全面的参考书。

Stroustrup因为吝于词句的写作风格而遭诟病,大家都知道我说过,如果阅读TC++PL(译者注:即The C++ Programming Language的简称。此书行文简洁)时,你无意忽略了哪怕一个句子,就有可能丢掉了很重要的东西(再想想目前版本千页以上的篇幅,你就能明白我为什么说它是最全面的参考书了)。然而,精炼恰是这本书无与伦比的魅力之一。比如,首版中对自赋值处理方法的说明,就再好不过证明了这一点:

if (this == &a) return; // beware of s=s;

首版《Effective C++》里,我在同样问题上花费了了五页半的篇幅。你不得不为这样一本半行注释就解决问题的图书倾倒。

《Effective C++》,作者Scott Meyers,Addison-Wesley出版社。1992年首版,1998年再版,2005年第三版。它是超级天才的杰作!哦,不要吐,别在意。

我和此书都很幸运,它生逢其时。1991年前后,大部分程序员已经掌握了语言基础,能做到根据需求编写C++程序,但同时总觉得自己无法避免看似可以避免的诸多问题。这是业界第一本专注于如何深入使用C++,全力帮助开发者解决常见问题,最好地使用非C特性(如构造器、析构器、继承、虚函数和类内存分配器等)的图书。在这本书里,一反常态,不像当时大多数人将重点放在讨论C++的灵活性上,我采用了一种很特别的指导式思路来写作。以我的经验判断,我认为程序员渴望找到强能有力的办法来控制C++的灵活多变,因此我要告诉他们究竟该做什么。这本书做到了。“一定要这么做”,“千万不要那样干”。一代程序员将这些原则熟记于心,也催生了不少协助性工具。比如Gnu C++编译器,甚至设置了《Effective C++》指导原则的检测警告选项[注1]。此书的一个重要特点——直到写作我的第二本书(《More Effective C++》)难以为继时,我才深入领会到——是其条款内容短小精悍,这样,读者坐公交车、火车,等待会议开始,甚至
我曾经说过的坐在马桶上时都可以阅读这本书。

《Design Patterns》,作者Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides。Addison-Wesley出版社,1995年。它本身不是一本针对C++的书,但它对使用C++以及其他任何面向对象编程语言进行良好设计都产生了深远影响。此书在专业软件开发人员中发起了模式启蒙运动,而且提出了一系列至今仍居常用模式词汇表核心地位的设计模式[注2]。如果你熟悉命令(Command)、访问者(Visitor)、装饰(Decorator)或单例(单态,Singleton)等模式——甚至已经深入掌握了设计模式,那么基本上可以肯定你读过这本书,我们应该感谢它。

此书中提到的模式,至今仍是C++技术界的热门话题。例如Herb Sutter于2003年9月,在其C/C++ Users Journal专栏提出了观察者(Observer)模式新的实现方法,Andrei Alexandrescu也分别于2005年4月和6月,在其C/C++ Users Journal专栏对这个模式做过讨论。

《International Standard for C++》,ISO/IEC。1998年首版,2003年第二版。标准类资料读起来枯燥乏味,但必须有这样的东西去定义什么是C++,什么不是C++,这本书就担此重任。在这以前,若想知道C++的正确实现,最好要读Margaret Ellis和Bjarne Stroustrup合著的《The Annotated C++ Reference Manual》(即著名的ARM,Addison-Wesley1990年版),并用不同的编译器检查代码,得想方设法理解Bjarne Stroustrup的意思(如通过读他的书)。1998年版的C++标准不能回答所有问题(任何资料都做不到),比如,vector的内存布局必须与C数组兼容吗?[注3] 但它仍不失为一本C++权威参考书,无论是为编程实现还是语言使用者,都在标准化上做出了巨大努力。2003年出的第二版,实际上是一个Bug修复更新版,更像是1.1而不是2.0版本,但它也是一个语言官方规范修订本。

《Modern C++ Design》,作者Andrei Alexandrescu。Addison-Wesley2001年版。设计模板的初衷是实现类型的容器(“containers of T”),但它能做的远不仅仅这点。实际上,在lexandrescu的书出现之前,1998版C++标准的STL部分要求的模板实现就远远超出“类型的容器”。但Modern C++ Design》的出现,才真正为C++技术界打破了模板的牢笼。此书影响深远,堪称新旧两代C++程序设计的分水岭;此后,“modern C++”一般都被用来专指采用了因此书而普及的模板技术的代码。通过Google搜索包含“modern C++”的新闻组帖子,1985到2000年共有662个结果,而从2001年到现在,则有3200个。

尽管无关于这本书在C++历史上的重要性,但我想有一点仍然值得提及,那就是在Alexandrescu写这本书的时候,他还找不到一个支持这本书的代码包含的所有C++标准的编译器!

当你再次浏览这个名单的时候,请记得我是Addison-Wesley的签约作家,这个身份使我有机会免费获得Addison-Wesley出版的任何优秀图书。因此,可能相对于其他出版社来说,我更熟悉的是Addison-Wesley的图书。不过,如果其他出版社有图书震撼了C++世界,我想我肯定也会听说过。

在本系列的下一篇文章里,我将选择C++历史上最重要的非图书出版物(如杂志的文章等)。

注1
即:-Weffc++。

注2
一直以来,我都有意在Google上搜索网页和新闻组最常提及的模式名,结果我发现多年来,20个最频繁提及的模式名,绝大部分出自这本书。这充分证明这本10年高龄的图书经久不衰。

注3
是的。

再说指针和数组

今天在书上看到大致这样的一段代码:
int main(int argc, char *argv[])
{
while (--argc)
printf("%s\n", *++argv);
return 0;
}

于是立刻感觉有地方不妥:++argv.
记得书上是说一个数组名代表的是一个常量指针,但是为何此处可以让一个数组名常量作自增运算呢?

为了证明我的理解的正确性,我还特地写了这么一段代码:
int main(int argc, char *argv[])
{
char *a[2] = {"1", "2"};
printf("%s %s\n", *a, *++a);
return 0;
}
编译:
greenlightzc@greenlightzc-desk:~/Desktop$ gcc -o test test.c
test.c: In function ‘main’:
test.c:6: error: invalid lvalue in increment

和我预期的一样。
但是为什么片段一可以通过编译呢?

原来是形参的问题:数组形参在编译的时候都是转换为指针类型的,也就是说char *argv[]作为形参的时候传进来的是参被转换为char **类型。

还要多亏豹仔和我一起讨论这个看似简单的问题呢: )

2007年4月22日星期日

eBay面经

早上是宣讲+笔试
笔试全英语的:单词填空+智力题+专业题(c++, 数据库, java)
下午寝室三人打牌,由于不确定名单,我一直没去。后来时至4点,那边的HR打电话给yinwei,于是我们赶了过去。

很幸运的是一面二面三面......开始的英语有点慌,然后越说约有信心。
最后那个老大私下和我说明天早上10点二楼见。

估计应该没有问题,可是我还在等baidu 的消息。
前几天去了趟我喜欢的ASK,结果觉得那个人很%^#*,失望,不说了。

2007年4月20日星期五

[ZZ]胡侃学习(理论)计算机

作者是南大毕业的,现在美国某校做教授
看完以后我实在不好意思说自己是计算机科学与技术专业的毕业生。

发信人: sir (阿涩), 信区: Mathematics
标 题: 胡侃学习(理论)计算机(0)
发信站: 南京大学小百合站 (Mon Oct 8 03:57:41 2001), 站内信件

我也来冒充一回高手,谈谈学习计算机的一点个人体会。
由于我是做理论的,所以先着重谈谈理论。

记得当年大一,刚上本科的时候,每周六课时数学分析,
六课时高等代数,天天作业不断(那时是六日工作制)。
颇有些同学惊呼走错了门:咱们这到底念的是什么系?
不错,你没走错门,这就是(当时的)南大计算机系。系
里的传统是培养做学术研究,尤其是理论研究的人。而
计算机的理论研究,说到底了就是数学,虽然也许是
正统数学家眼里非主流的数学。

数学分析这个东东,咱们学计算机的人对它有很复杂
的感情。爱它在于它是第一门,也是学分最多的一门
数学课,又长期为考研课程--94以前可以选考数学分析
与高等代数,以后则并轨到著名的所谓“工科数学一”。
其重要性可见一斑。恨它则在于它好象难得有用到的
机会,而且思维跟咱们平常做的这些离散/有限的工作
截然不同。当年出现的怪现象是:计算机系学生的高中
数学基础在全校数一数二(希望没有冒犯其它系的同学),
教学课时数也仅次于数学系,但学完之后的效果却几
乎是倒数第一。其中原因何在,发人深思。

我个人的浅见是:计算机类的学生,对数学的要求固然
跟数学系不同,跟物理类差别则更大。通常非数学专业
的所谓“高等数学”,无非是把数学分析中较困难的理论
部分删去,强调套用公式计算而已。而对计算机系来说,
数学分析里用处最大的恰恰是被删去的理论部分。说得
难听一点,对计算机系学生而言,追求算来算去的所谓
“工科数学一”已经彻底地走进了魔道。记上一堆曲面积分
的公式,难道就能算懂了数学分析?

中文的数学分析书,一般都认为以北大张筑生老师的
“数学分析新讲”为最好。我个人认为南大数学系的“数学
分析教程”也还不错,至少属于典型的南大风格,咱们
看着亲切。随便学通哪一本都行。万一你的数学实在
太好,这两本书都吃不饱,那就去看菲赫金哥尔茨的
“微积分学教程”好了--但我认为没什么必要,毕竟你
不想转到数学系去。

吉米多维奇的“数学分析习题集”也基本上是计算型的
东东。如果你打算去考那个什么“工科数学一”,可以
做一做。否则,不做也罢。

中国的所谓高等代数,就等于线性代数加上一点多项式
理论。我以为这有好的一面,因为可以让学生较早感觉
到代数是一种结构,而非一堆矩阵翻来覆去。当年我们
用林成森,盛松柏两位老师编的“高等代数”,感觉相当
舒服,我直到现在还保留着教材。此书相当全面地包含
了关于多项式和线性代数的基本初等结果,同时还提供
了一些有用的比较深的内容,如Sturm序列,Shermon
-Morrison公式,广义逆矩阵等等。可以说,作为本科
生如能吃透此书,就可以算高手。后来它得以在南大出
版社出版,可惜好象并轨以后就没有再用了。

国内较好的高等代数教材还有清华计算机系用的那本,
清华出版社出版,书店里多多,一看就知道。特点嘛,
跟南大那本差不太多。

但以上两本书也不能说完美无缺。从抽象代数的观点
来看,高等代数里的结果不过是代数系统性质的一些
例子而已。莫宗坚先生的“代数学”里,对此进行了深刻
的讨论。然而莫先生的书实在深得很,作为本科生恐
怕难以接受,不妨等到自己以后成熟了一些再读。

概率论与数理统计这门课很重要,可惜少了些东西。

少了的东西是随机过程。到毕业还没有听说过Markov
过程,此乃计算机系学生的耻辱。没有随机过程,
你怎么分析网络和分布式系统?怎么设计随机化算法
和协议?据说清华计算机系开有“随机数学”,早就是
必修课。人家可是工科学校,作为自以为“理科计算机
系”出身的人,我感到惭愧。

另外,离散概率对计算机系学生来说有特殊的重要性。
现在,美国已经有些学校开设了单纯的“离散概率论”
课程,干脆把连续概率删去,把离散概率讲深些。我们
不一定要这么做,但应该更加强调离散概率是没有疑
问的。

计算方法是最后一门由数学系给我们开的课。一般学生对
这门课的重视程度有限,以为没什么用。其实,做图形
图像可离不开它。而且,在很多科学工程中的应用计算,
都以数值的为主。

这门课有两个极端的讲法:一个是古典的“数值分析”,
完全讲数学原理和算法;另一个是现在日趋流行的“科学
与工程计算”,干脆教学生用软件包编程。南大数学系
的几位老师做了件大好事,把前者的一本极为经典的
教材翻译出版了:德国Stoer的“数值分析引论”。如果
你能学会此书中最浅显的三分之一,就算没有白上过
计算方法这门课!而后一种讲法似乎国内还没有跟上
潮流?不过,只要你有机会在自己的电脑上装个matlab
之类,完全可以无师自通。

本系里,通常开一门离散数学,包括集合论,图论,
和抽象代数,另外再单开一门数理逻辑。这样安排,
主要由于南大的逻辑传统:系里很多老师都算莫先生
的门人,就连孙先生都是逻辑专业出身(见孙先生自
述)。

不过,这么多内容挤在离散数学一门课里,是否
时间太紧了点?另外,计算机系学生不懂组合和
数论,也是巨大的缺陷。要做理论,不懂组合或
者数论吃亏可就太大了。

从理想的状态来看,最好分开六门课:集合,
逻辑,图论,组合,代数,数论。这个当然不现实,
因为没那么多课时。也许将来可以开三门课:集合
与逻辑,图论与组合,代数与数论。

不管课怎么开,学生总一样要学。下面分别谈
谈上面的三组内容。

古典集合论,北师大出过一本“基础集合论”不错。
南大出版朱梧(木贾)老师的“集合论导引”也许观点更
高些,但他的书形式化得太厉害,念起来吃力。

数理逻辑,莫先生的书自然是经典。然而我们也
不得不承认,此书年代久远,光读它恐怕不够。
尤其是命题/谓词演算本身有好多种不同的讲法,
多看几家能大大开阔自己的视野。例如陆钟万老师
的“面向计算机科学的数理逻辑”就不错。朱老师也
著有“数理逻辑教程”一书,但也同样读起来费力些。

总的来说,学集合/逻辑起手不难,但越往后越感觉
深不可测。建议有兴趣的同学读读朱老师的“数学
基础引论”--此书有点时间简史的风格,讲到精彩处,
所谓“天花乱坠,妙雨缤纷”,令人目不暇接。读完
以后,你对这些数学/哲学中最根本的问题有了个大概
了解,也知道了山有多高,海有多深。
学完以上各书之后,如果你还有精力兴趣进一步
深究,那么可以试一下GTM系列中的"Introduction
to Axiomatic Set Theory"和"A Course of Mathematical
Logic"。这两本都有世界图书的引进版。你如果
能搞定这两本,可以说在逻辑方面真正入了门,
也就不用再浪费时间听我瞎侃了。:)

据说全中国最多只有三十个人懂图论(当年上课时陈道蓄
老师转引张克民老师的话)。此言不虚。图论这东东,
技巧性太强,几乎每题都有一个独特的方法,让人头痛。
不过这也正是它魅力所在:只要你有创造性,它就能
给你成就感。所以学图论没什么好说的,做题吧。

国内的图论书中,王树禾老师的“图论及其算法”非常
成功。一方面,其内容在国内教材里算非常全面的。
另一方面,其对算法的强调非常适合计算机系(本来
就是科大计算机系教材)。有了这本书为主,再参考
几本翻译的,如Bondy&Murty的“图论及其应用”,
邮电出版社翻译的“图论和电路网络”等等,就马马
虎虎,对本科生足够了。

再进一步,世界图书引进有GTM系列的"Modern
Graph Theory"。此书确实经典!国内好象还有一
家出版了个翻译版。不过,学到这个层次,还是
读原版好。搞定这本书,也标志着图论入了门,呵呵。
组合感觉没有太适合的国产书。还是读Graham和Knuth
等人合著的经典“具体数学”吧,有翻译版,西电出的。

抽象代数,国内经典为莫宗坚先生的“代数学”。此书
是北大数学系教材,深得好评。然而对本科生来说,
此书未免太深。可以先学习一些其它的教材,然后
再回头来看“代数学”。国际上的经典可就多了,GTM
系列里就有一大堆。推荐一本谈不上经典,但却最简
单的,最容易学的:
http://www.math.miami.edu/...
这本“Introduction to Linear and Abstract Algebra"
非常通俗易懂,而且把抽象代数和线性代数结合起来,
对初学者来说非常理想。不过请注意版权问题,不要
违反法律噢。

数论方面,国内有经典而且以困难著称的”初等数论“
(潘氏兄弟著,北大版)。再追溯一点,还有更加经典
(可以算世界级)并且更加困难的”数论导引“(华罗庚先生
的名著,科学版,九章书店重印)。把基础的几章搞
定一个大概,对本科生来讲足够了。但这只是初等数
论。本科毕业后要学计算数论,你必须看英文的书,
如Bach的"Introduction to Algorithmic Number Theory"

理论计算机的根本,在于算法。现在系里给本科生
开设算法设计与分析,确实非常正确。环顾西方世界,
大约没有一个三流以上计算机系不把算法作为必修的。

算法教材目前公认以Corman等著的"Introduction to
Algorithms"为最优。对入门而言,这一本已经足够,
不需要再参考其它书。南大曾翻译出版此书,中文名
为”现代计算机常用数据结构与算法“。pie好象提供了
网上课程的link,我也就不用废话。

最后说说形式语言与自动机。我们用过北邮的教材,
应该说写的还清楚。但是,有一点要强调:形式语言
和自动机的作用主要在作为计算模型,而不是用来
做编译。事实上,编译前端已经是死领域,没有任何
open problem。如果为了这个,我们完全没必要去学
形式语言--用用yacc什么的就完了。北邮的那本,在深
度上,在跟可计算性的联系上都有较大的局限,现代
感也不足。所以建议有兴趣的同学去读英文书......不过
英文书中好的也不多,而且国内似乎没引进这方面的
教材。

入门以后,把形式语言与自动机中定义的模型,和
数理逻辑中用递归函数定义的模型比较一番,可以
说非常有趣。现在才知道,什么叫”宫室之美,百官
之富“!

发信人: sir (阿涩), 信区: Mathematics
标 题: 胡侃学习计算机--理论之外(0)
发信站: 南京大学小百合站 (Mon Oct 15 05:26:00 2001), 站内信件

如果计算机只有理论,那么它不过是数学的一个分支,而
不成为一门独立的科学。事实上,在理论之外,计算机
科学还有更广阔的天空。我一直认为,4年根本不够学习
计算机的基础知识,因为面太宽了......


一个一流计算机系的优秀学生决不该仅仅是一个编程高
手,但他一定首先是一个编程高手。

我上大学的时候,第一门专业课时程序设计,现在好象
改成了计算机科学导论?不管叫什么名字,总之,念计
算机的人就是靠程序吃饭。

去年在计算机系版有过一场争论,关于第一程序设计语言
该用哪一种。我个人认为,用哪种语言属于末节,关键在
养成良好的编程习惯。当年老师对我们说,打好基础后
学一门新语言只要一个星期。现在我觉得根本不用一个
星期--前提是先把基础打好。

数据结构有两种不同的上法:一种把它当成降低要求的
初级算法课,另一种把它当成高级的程序设计课。现在
国内的课程好象介乎两者之间,而稍偏向前者。我个人
认为,假如已经另有必修的算法课,恐怕后一个目的更
重要些。

国内流行的数据结构书也有两种:北大的红皮书(许卓
群等著,高教版)和清华的绿皮书(严蔚敏等著,清华版)。
两书差距不大。红皮书在理论上稍深一些,当然离严格
的算法书还差好远。绿皮书更易接受些,而且佩有一本
不错的习题集,但我觉得它让学生用伪代码写作业恐怕
不见得太好。最好还是把算法都code以后debug一番,
才能锻炼编程能力。

汇编预言和微机原理是两门特烦人的课。你的数学/理论
基础再好,也占不到什么便宜。这两门课之间的次序也
好比先有鸡还是先有蛋,无论你先学哪门,都会牵扯另
一门课里的东西。所以,只能静下来慢慢琢磨。这就是
典型的工程课,不需要太多的聪明和顿悟,却需要水滴
石穿的渐悟。

有关这两门课的书,电脑书店里不难找到。弄几本最新
的,对照着看吧。

模拟电路这东东,如今不仅计算机系学生搞不定,
电子系学生也多半害怕。如果你真想软硬件通吃,那么
建议你先看看邱关源的“电路原理”,也许此后再看模拟
电路底气会足些。

教材:康华光的“电子技术基础”还是不错的。有兴趣也
可以参考童诗白的书。

数字电路比模拟电路要好懂得多。阎石的书也算一本好
教材,遗憾的一点是集成电路讲少了些。真有兴趣,到
东南无线电系去旁听他们的课。

计算机系统结构该怎么教,国际上还在争论。国内能找
到的较好教材为Stallings的"Computer Organization
and Architecture:Designing for Performance"(清华影印
本)。国际上最流行的则是“Computer architecture: a
quantitative approach", by Patterson & Hennessy。

操作系统可以随便选用Tanenbaum的"Operating System
Design and Implementation"和"Modern Operating
System"两书之一。这两部都可以算经典,唯一缺点
就是理论上不够严格。不过这领域属于Hardcore System,
所以在理论上马虎一点也情有可原。

如果先把形式语言学好了,则编译原理中的前端我看只要
学四个算法:最容易实现的递归下降;最好的自顶向下
算法LL(k);最好的自底向上算法LR(k);LR(1)的简
化SLR(也许还有另一简化LALR?)。后端完全属于工程
性质,自然又是another story。

推荐教材:
Aho等人的著名的Dragon Book: "Compilers: Principles,
Techniques and Tools".
或者Appel的"Modern Compiler Implementation in C".

学数据库的第一意义是告诉你,会用VFP编程不等于懂
数据库。(这世界上自以为懂数据库的人太多了!)数据库
设计既是科学又是艺术,数据库实现则是典型的工程。
所以从某种意义上讲,数据库是最典型的一门计算机课
--理工结合,互相渗透。

推荐教材:Silberschatz, et al., "Database System
Concepts".

网络的标准教材还是来自Tanenbaum:”Computer
Networks"(清华影印本)。不过,网络也属于Hardcore
System,所以光看书是不够的。建议多读RFC,从
IP的读起。等到能掌握10种左右常用协议,就没有几个
人敢小看你了。

必须结束这篇“胡侃”了,再侃下去非我力所能及。其实
计算机还有很多基础课都值得一侃,如程序设计语言原
理,图形图像处理,人工智能等等。怎奈我造诣有限,
不敢再让内行耻笑。

最后声明:前后的两篇“胡侃”只针对本科阶段的学习。
即使把这些全弄通了,前面的路还长......

2007年4月19日星期四

你最想见到的浙籍IT精英

居然看到老板的名字了,太赞了:)

投票结果
正常排序 从高到低 从低到高

你最想见到的浙籍IT精英(排名不分先后)
原北京联众电脑技术有限责任公司CEO兼总裁鲍岳桥: 33票3.34%
浙大网新科技股份有限公司董事长陈纯: 22票2.22%
上海盛大网络发展有限公司创始人,董事长兼CEO陈天桥: 64票6.47%
中国搜索总裁陈沛: 15票1.51%
网易公司CEO丁磊: 67票6.78%
北京博客网信息技术有限公司董事长兼CEO方兴东: 52票5.26%
上海复星高科技(集团)有限公司董事长郭广昌: 23票2.32%
杭州天畅网络科技有限公司董事长郭羽: 13票1.31%
中国博客网CEO胡之光: 5票0.50%
分众传媒(中国)控股有限公司创始人、董事长江南春: 45票4.55%
浙江大学快威科技集团有限公司总裁蒋忆: 9票0.91%
游侠网CEO郦彦卿: 5票0.50%
阿里巴巴创办人、主席、首席执行官(CEO) 马云: 75票7.59%
金山软件股份有限公司董事长求伯君: 34票3.44%
四川托普集团科技发展有限责任公司主席兼CEO宋如华: 21票2.12%
浙江网盛科技股份有限公司总裁孙德良: 63票6.37%
eBay易趣董事长邵亦波: 82票8.29%
e龙公司董事长唐越: 81票8.19%
杭州富通集团有限公司董事长王建沂: 16票1.61%
中国•颐高集团有限公司董事长翁南道: 163票16.49%
浙大网新科技股份有限公司总裁赵建: 12票1.21%
赛伯乐(中国)创业投资管理有限公司董事长朱敏: 33票3.34%
Google执行总裁周韶宁: 5票0.50%
杭州华三通信技术有限公司总裁兼首席运营官郑树生: 50票5.06%

春回燕归.浙籍精英峰会

前几天丁磊,孙德良,吴晓波三人来我校作演讲,主题是“互联网的前十年,后十年”

三人的故事不必多说了。
最后丁磊的一席话确实让人受益,具体是什么我已经刻在脑子里了。
末了,没时间找丁磊签名了,因为约好了4个兄弟踢球,赶紧走人了...

昨天暴跌今天暴涨

“暴跌拉开阶段性调整序幕”——Yahoo!中国
昨天跌的我没什么感觉,因为我第一反应是大盘要把散户震荡出局;
今天果然涨得我爽,更加坚定了我的信念了,必定是操盘者的把戏。想骗大伙出市...

敌人拥护的我们就要反对,敌人反对的我们就要拥护!

baidu:获得二面机会

曲二
前天和Phd洪的见面让我收获不小。但是我一直没有把能不能去baidu实习太放在心上,因为我觉得自己表现的并不出色。但是很意外的是同行的几个兄弟只有我收到的北京过来的电话,那边和我约好了一个时间电话面试。
这次还是和上次一样,实现没有作任何准备,因为星期六我和豹仔,菠菜去紫荆港参加ACM比赛,也没什么时间看书。倒是到了电面前的几个小时,我网上找了点资料,主要看了分类聚类的东东。
然后静静的回忆了第一次面试的过程,预测二面会问的一些东西。

下午2点,百度工程师准时地打电话过来。一阵%^&$#*之后,进入技术话题&*^$%#还是和PHD洪问的差不多,于是我很顺利的&^#*$@。然后说到几个高深一点的话题,先是STL的缺陷:内存分配,线程不安全等,我解释到:STL的实现机制我没有看过,被BS了;然后到了算法部分:AVL树的特点以及如何维持这个特点的,*&……%¥#,ok。
最后一个问题是最tmd bt的:请讲述一下hash, b tree, b+ tree各自的特点,优劣以及适用场合。
先是汗了一把,然后静静的想了片刻,决定先说hash。还好寒假写Nokia那个项目的时候自己把一个PC版本的hash实现、修改成一个symbian版本,所以那里面的东西就相对熟悉了,&*^$%#,ok;b和b+树这个问题说实话我是答出了40%,特别是后面那个各自的优劣真是bt。我印象中b+树似乎都是优于b树的,而且在数据库管理的底层细节上也是使用b+的,怎么b树也有优势?被BS了,原来b树和b+的细节我还是有很多没有搞清楚的,就是因为这个原因我最近就在看《数据库系统实现》这本讲数据库实现细节的书。

最后他让我文他一个问题,我就让他告诉我b,b+之间的优劣性,原来*&^%#$。。。土了。
结束前,对方问我什么时间段可以过去,我说7-10月,他说好的。于是终了。
突然忘记问他什么时候可以知道结果,sigh,害的我这几天天天查邮件查的频繁。

baidu:我的处女面经

曲一
有幸能得到zdwaiter的内部推荐直接和百度科学家洪涛面对面进行了长达一个小时的交流。由于事先没有任何准备的就去裸面,因此也就谈不上紧张的问题了,本来就是去学习学习的嘛。

PhD 洪非常和蔼的和我互相打了招呼。初见此人感觉分外亲切,邻家大叔的味道。听着他的口音像北方人,但是他却说自己是土生土长的浙江人。于是我就借着这个话题和他攀谈起来。他热情的介绍了一下自己的情况:温州人,留美,微软工作,最后去了百度。说到我的情况的时候他还和我聊起了家常,因为他的舅舅居然在浙工大教书(如果我没听错的话)...

接着,是例行的技术问题,主要围绕了我做得那个Nokia基于移动终端的基于意图的个性化查询支撑系统。问的非常细致,从架构到实现,在到实现中遇到的困难,还问了相关的“个性化”和“查询意图”的理解问题。之后问到了我最近在做的sqlite裁剪的项目,项目思路等。这些都回答的比较顺利,毕竟是手头在弄的东西。

最后说到了两个算法题目,一个是如何判断一个Link-list存在回路的问题,另一个是对一个给定的长度为N的数组(已知这个数组有一个元素的出现次数大于N/2),找出其中出现次数大于N/2的那个元素。第一个问题我20秒就给出了一个可行的解:用一个bit标识是否被访问过,每次遍历之前都检查这个bit即可,但是PhD洪认为这不是最优解,如果这个链的长度在百万级别以上的话空间的开销是十分巨大的;然后又过了几分钟我想到了第二种办法(事后证明这个方法是错误的):用两个指针,一前一后遍历,pre指着某一个元素,让cur往前走,如果pre和cur有重逢的话那么存在环路。他先停顿了一下,然后问道:你确定这个方法可以保证找出任何环么?原来我忽略了一种情况:非首尾环的问题。但是我觉得我的这两个回答也算过得去了,至少说明我还是懂一点数据结构的:)。第二个问题我开始也是很sb的要开一个辅助空间记录,当然也是不满足大数据量的要求的。时间已经过了1个小时了,Phd洪也就直接和我说答案了,其实真tmd简单,纯粹是个要求细致观察的问题,唉。

临走前他嘱咐我给baidu发一个电子版本的简历,就这么结束了。非常有意思的一次经历。

脚本

shell+sed+awk
三者中功能最弱,没有调试程序,大多数操作必须通过运行其他程序才能执行,所以需要更多时间、内存并在进程表中占有位置。内置的算术运算很有限,数组下标必须是数字等。但它对运行环境要求低,小巧便捷,是学习系统脚本编程的基础。

Perl
设计之初就是为了方便编写复杂高效的系统脚本,它也是应该最为广泛的脚本编程语言。它在编程方面相当于瑞士军刀,对字符、文本文件处理能力很强,以前要求 shell+sed+awk+C才能完成的任务,只需perl脚本就可以完成了。而且应用领域一直在拓宽,支持面向对象程序设计。

Python
面向对象的动态公共语言,适于脚本编程和快速开发,它最显著的特点是作为编译语言(如C)和脚本语言(如perl)之间的桥接语言,它具有的强大功能,可扩充性及面向对象的特征使其成为大规模应用程序开发工具。

由此可见Perl比shell+sed+awk更强大,但学习两者并不冲突,通常是学习shell做为脚本编程的入门基础。而Python在应用领域则与 前两者有很大的差别,无太大的可比性。面向不同的任务,可以只需用到其中的一种,也可能三种都要用到,所以究竟该学谁不学谁,需要由面对的任务来决定。

2007年4月16日星期一

NANA

早上起来,例行地打开邮箱收邮件,却被网页中的这个叫NANA的漫画所吸引。因为它让我想起了某些人某些事,我把下面这第一张作为现在的桌面了...

“ 我喜欢回味, 记忆的美..."


[zoj 2833] Friendship

Friendship

Time limit: 3 Seconds Memory limit: 32768K
Total Submit: 908 Accepted Submit: 195

A friend is like a flower,
a rose to be exact,
Or maybe like a brand new gate
that never comes unlatched.

A friend is like an owl,
both beautiful and wise.
Or perhaps a friend is like a ghost,
whose spirit never dies.

A friend is like a heart that goes
strong until the end.
Where would we be in this world
if we didn't have a friend?

- By Emma Guest

Now you've grown up, it's time to make friends. The friends you make in university are the friends you make for life. You will be proud if you have many friends.

Input

There are multiple test cases for this problem.

Each test case starts with a line containing two integers N, M (1 <= N <= 100'000, 1 <= M <= 200'000), representing that there are totally N persons (indexed from 1 to N) and M operations, then M lines with the form "M a b" (without quotation) or "Q a" (without quotation) follow. The operation "M a b" means that person a and b make friends with each other, though they may be already friends, while "Q a" means a query operation.

Friendship is transitivity, which means if a and b, b and c are friends then a and c are also friends. In the initial, you have no friends except yourself, when you are freshman, you know nobody, right? So in such case you have only one friend.

Output

For each test case, output "Case #:" first where "#" is the number of the case which starts from 1, then for each query operation "Q a", output a single line with the number of person a's friends.

Separate two consecutive test cases with a blank line, but Do NOT output an extra blank line after the last one.

Sample Input

3 5
M 1 2
Q 1
Q 3
M 2 3
Q 2
5 10
M 3 2
Q 4
M 1 2
Q 4
M 3 2
Q 1
M 3 1
Q 5
M 4 2
Q 4

Sample Output

Case 1:
2
1
3

Case 2:
1
1
3
1
4

Notes

This problem has huge input and output data, please use 'scanf()' and 'printf()' instead of 'cin' and 'cout' to avoid time limit exceed.

Author: LIU, Yaoting


Problem Source: Zhejiang University Local Contest 2007, Preliminary

07校赛预赛的最后一道题目,也是由我负责作的,结果没出来,对不起大家啊T_T。比赛的时候用了set和map,但是这道题目数据量很大,这样会超时的。所以回去看了下书后改用disjoint set,而且内部是用森林的数据结构解决的而不用链表,主要还是担心速度的问题嘛。

#include
typedef struct
{
int p;
int r;
int v;
}NODE;

#define MAKE_SET(x) {(x).p = (x).v; (x).r = 1;}

#define MAXLEN 100001

NODE s [MAXLEN];

inline int FIND_SET(NODE s [], int x)
{
while ( s[x].v != s[x].p )
x = s[x].p;
return x;
}

inline void LINK(NODE &x, NODE &y)
{
if (x.r > y.r)
{
y.p = x.v;
x.r += y.r;
}
else
{
x.p = y.v;
y.r += x.r;
}
}

inline void UNION(NODE s [], int x, int y)
{
LINK(s[FIND_SET(s, x)], s[FIND_SET(s, y)]);
}

int main()
{
int n, m;
bool first = true;
int cc = 1;



while (scanf("%d %d", &n, &m) != EOF)
{
for (int i = 0; i < MAXLEN; ++i)
{
s[i].v = i;
MAKE_SET(s[i]);
}

bool second = true;

if (!first)
printf("\n");

while (m--)
{
char line;
char c;
scanf("%c %c", &line, &c);

if (c == 'M')
{
int x, y;
scanf("%d %d", &x, &y);

if (FIND_SET(s, x) != FIND_SET(s, y))
UNION(s, x, y);

}
else
{
if (second)
{
printf("Case %d:\n", cc);
second = false;
}

int q;
scanf("%d", &q);

if (s[q].p == s[q].v && s[q].r == 1)
{
printf("1\n");
continue;
}
int pp = FIND_SET(s, q);
printf("%d\n", s[pp].r);


}
}

first = false;
++cc;
}
return 0;
}

[zoj 2840] File Searching

File Searching

Time limit: 1 Seconds Memory limit: 32768K
Total Submit: 161 Accepted Submit: 37

Have you ever used file searching tools provided by an operating system? For example, in DOS, if you type "dir *.exe", the OS will list all executable files with extension "exe" in the current directory. These days, you are so mad with the crappy operating system you are using and you decide to write an OS of your own. Of course, you want to implement file searching functionality in your OS.

Input:

The input contains several test cases. Consecutive test cases are separated by a blank line.

Each test case begins with an integer N (1 <= N < =100), the number of files in the current directory. Then N lines follow, each line has one string consisting of lowercase letters ('a'..'z') and the dot ('.') only, which is the name of a file. Then there is an integer M (1 <= M <= 20), the number of queries. M lines follow, each has one query string consisting of lowercase letters, the dot and the star ('*') character only. Note that the star character is the "universal matching character" which is used to represent zero or numbers of characters that are uncertain. In the beginning, you just want to write a simple version of file searching, so every string contains no more than 64 characters and there is one and only one star character in the query string.

Process to the End Of File (EOF).

Output:

For each test case, generate one line for the results of each query. Separate file names in the result by a comma (',') and a blank (' ') character. The file names in the result of one query should be listed according to the order they appear in the input. If there is no matching file, output "FILE NOT FOUND" (without the quotation) instead.

Separate two consecutive test cases with a blank line, but Do NOT output an extra blank line after the last one.

Sample Input:
4
command.com
msdos.sys
io.sys
config.sys
2
com*.com
*.sys

3
a.txt
b.txt
c.txt
1
*.doc

Sample Output:
command.com
msdos.sys, io.sys, config.sys

FILE NOT FOUND

Author: ZHOU, Yuan


Problem Source: Zhejiang University Local Contest 2007

这道题目就是我们决赛时候的一道诡异题目,我和菠菜一起讨论了几种测试用例,但是一直没有发现aaa和aa*aa这个特殊的用例,一直WA至最后一分钟。惨痛啊。回到寝室后把下午写的代码全部扔掉重来,重写代码,并且放弃使用STL,终于AC了。
基本思路就是star在中间,左边,右边和仅有一个star的情况分别讨论。代码不是很简洁,老大貌似有更精简的分类,不管了...

#include
#include

using namespace std;

char a[100][100];

#define NOT_FOUND "FILE NOT FOUND\n"

enum CMD {ALL = 1, LEFT, RIGHT, MID};
int main()
{
int n;
bool first = true;
while (scanf("%d", &n) != EOF)
{
if (!first)
printf("\n");
first = false;

int i = 0;
while (i < len =" i;" f =" true;" i =" 0;" size =" strlen(q);" size ="="" cmd =" ALL;" cmd =" LEFT;" i ="=""> 1)
cmd = RIGHT;
else
cmd = MID;
}
}

int star = i;
int j, k;

switch (cmd)
{
case ALL:
for (i = 0; i < f =" false;" i =" 0;" j =" strlen(a[i])" k =" size">= 0 && k > star; --j, --k)
{
if (q[k] != a[i][j])
break;
}
if (k == star)
{
if (!f)
printf(", ");
f = false;
printf("%s", a[i]);
}
}
if (f)
printf(NOT_FOUND);
else
printf("\n");
break;

case RIGHT:
for (i = 0; i < j =" 0," k =" 0;" k ="="" f =" false;" i =" 0;" j =" 0," k =" 0;" tmp =" j;" k ="="" j =" strlen(a[i])" k =" size"> star &&amp; j >= tmp; --j, --k)
{
if (q[k] != a[i][j])
break;
}
if (k == star)
{
if (!f)
printf(", ");
f = false;
printf("%s", a[i]);

}
}
}
if (f)
printf(NOT_FOUND);
else
printf("\n");
break;

default:
break;
}
}
}
return 0;
}

[ZZ]李开复:算法的力量

算 法是计算机科学领域最重要的基石之一,但却受到了国内一些程序员的冷落。许多学生看到一些公司在招聘时要求的编程语言五花八门就产生了一种误解,认为学计 算机就是学各种编程语言,或者认为,学习最新的语言、技术、标准就是最好的铺路方法。其实大家都被这些公司误导了。编程语言虽然该学,但是学习计算机算法 和理论更重要,因为计算机算法和理论更重要,因为计算机语言和开发平台日新月异,但万变不离其宗的是那些算法和理论,例如数据结构、算法、编译原理、计算 机体系结构、关系型数据库原理等等。在“开复学生网”上,有位同学生动地把这些基础课程比拟为“内功”,把新的语言、技术、标准比拟为“外功”。整天赶时 髦的人最后只懂得招式,没有功力,是不可能成为高手的。


算法与我

当我在1980年转入计算机科学系时,还没有多少人的专业方向是计算机科学。有许多其他系的人嘲笑我们说:“知道为什么只有你们系要加一个‘科学 ’,而没有‘物理科学系’或‘化学科学系’吗?因为人家是真的科学,不需要画蛇添足,而你们自己心虚,生怕不‘科学’,才这样欲盖弥彰。”其实,这点他们 彻底弄错了。真正学懂计算机的人(不只是“编程匠”)都对数学有相当的造诣,既能用科学家的严谨思维来求证,也能用工程师的务实手段来解决问题——而这种 思维和手段的最佳演绎就是“算法”。

记得我读博时写的Othello对弈软件获得了世界冠军。当时,得第二名的人认为我是靠侥幸才打赢他,不服气地问我的程序平均每秒能搜索多少步棋, 当他发现我的软件在搜索效率上比他快60多倍时,才彻底服输。为什么在同样的机器上,我可以多做60倍的工作呢?这是因为我用了一个最新的算法,能够把一 个指数函数转换成四个近似的表,只要用常数时间就可得到近似的答案。在这个例子中,是否用对算法才是能否赢得世界冠军的关键。

还记得1988年贝尔实验室副总裁亲自来访问我的学校,目的就是为了想了解为什么他们的语音识别系统比我开发的慢几十倍,而且,在扩大至大词汇系统 后,速度差异更有几百倍之多。他们虽然买了几台超级计算机,勉强让系统跑了起来,但这么贵的计算资源让他们的产品部门很反感,因为“昂贵”的技术是没有应 用前景的。在与他们探讨的过程中,我惊讶地发现一个O(n*m)的动态规划(dynamic programming)居然被他们做成了O (n*n*m)。更惊讶的是,他们还为此发表了不少文章,甚至为自己的算法起了一个很特别的名字,并将算法提名到一个科学会议里,希望能得到大奖。当时, 贝尔实验室的研究员当然绝顶聪明,但他们全都是学数学、物理或电机出身,从未学过计算机科学或算法,才犯了这么基本的错误。我想那些人以后再也不会嘲笑学 计算机科学的人了吧!


网络时代的算法

有人也许会说:“今天计算机这么快,算法还重要吗?”其实永远不会有太快的计算机,因为我们总会想出新的应用。虽然在摩尔定律的作用下,计算机的计 算能力每年都在飞快增长,价格也在不断下降。可我们不要忘记,需要处理的信息量更是呈指数级的增长。现在每人每天都会创造出大量数据(照片,视频,语音, 文本等等)。日益先进的纪录和存储手段使我们每个人的信息量都在爆炸式的增长。互联网的信息流量和日志容量也在飞快增长。在科学研究方面,随着研究手段的 进步,数据量更是达到了前所未有的程度。无论是三维图形、海量数据处理、机器学习、语音识别,都需要极大的计算量。在网络时代,越来越多的挑战需要靠卓越 的算法来解决。

再举另一个网络时代的例子。在互联网和手机搜索,如果要找附近的咖啡店,那么搜索引擎该怎么处理这个请求呢?最简单的办法就是把整个城市的咖啡馆都 找出来,然后计算出它们的所在位置与你之间的距离,再进行排序,然后返回最近的结果。但该如何计算距离呢?图论里有不少算法可以解决这个问题。

这么做也许是最直观的,但绝对不是最迅速的。如果一个城市只有为数不多的咖啡馆,那么这么做应该没什么问题,反正计算量不大。但如果一个城市里有很多咖啡馆,又有很多用户都需要类似的搜索,那么服务器所承受的压力就大多了。在这种情况下,我们该怎样优化算法呢?

首先,我们可以把整个城市的咖啡馆做一次“预处理”。比如,把一个城市分成若干个“格子(grid)”,然后根据用户所在的位置把他放到某一个格子里,只对格子里的咖啡馆进行距离排序。

问题又来了,如果格子大小一样,那么绝大多数结果都可能出现在市中心的一个格子里,而郊区的格子里只有极少的结果。在这种情况下,我们应该把市中心 多分出几个格子。更进一步,格子应该是一个“树结构”,最顶层是一个大格——整个城市,然后逐层下降,格子越来越小,这样有利于用户进行精确搜索——如果 在最底层的格子里搜索结果不多,用户可以逐级上升,放大搜索范围。

上述算法对咖啡馆的例子很实用,但是它具有通用性吗?答案是否定的。把咖啡馆抽象一下,它是一个“点”,如果要搜索一个“面”该怎么办呢?比如,用 户想去一个水库玩,而一个水库有好几个入口,那么哪一个离用户最近呢?这个时候,上述“树结构”就要改成“r-tree”,因为树中间的每一个节点都是一 个范围,一个有边界的范围(参考:http://www.cs.umd.edu/~hjs/rtrees/index.html)。

通过这个小例子,我们看到,应用程序的要求千变万化,很多时候需要把一个复杂的问题分解成若干简单的小问题,然后再选用合适的算法和数据结构。


并行算法:Google的核心优势

上面的例子在Google里就要算是小case了!每天Google的网站要处理十亿个以上的搜索,GMail要储存几千万用户的2G邮箱, Google Earth要让数十万用户同时在整个地球上遨游,并将合适的图片经过互联网提交给每个用户。如果没有好的算法,这些应用都无法成 为现实。

在这些的应用中,哪怕是最基本的问题都会给传统的计算带来很大的挑战。例如,每天都有十亿以上的用户访问Google的网站,使用Google的服 务,也产生很多很多的日志(Log)。因为Log每份每秒都在飞速增加,我们必须有聪明的办法来进行处理。我曾经在面试中问过关于如何对Log进行一些分 析处理的问题,有很多面试者的回答虽然在逻辑上正确,但是实际应用中是几乎不可行的。按照它们的算法,即便用上几万台机器,我们的处理速度都根不上数据产 生的速度。

那么Google是如何解决这些问题的?

首先,在网络时代,就算有最好的算法,也要能在并行计算的环境下执行。在Google的数据中心,我们使用的是超大的并行计算机。但传统的并行算法 运行时,效率会在增加机器数量后迅速降低,也就是说,十台机器如果有五倍的效果,增加到一千台时也许就只有几十倍的效果。这种事半功倍的代价是没有哪家公 司可以负担得起的。而且,在许多并行算法中,只要一个结点犯错误,所有计算都会前功尽弃。

那么Google是如何开发出既有效率又能容错的并行计算的呢?

Google最资深的计算机科学家Jeff Dean认识到,Google所需的绝大部分数据处理都可以归结为一个简单的并行算法:Map and Reduce(http://labs.google.com/papers/mapreduce.html)。 这个算法能够在很多种计算中达到相当高的效率,而且是可扩展的(也就是说,一千台机器就算不能达到一千倍的效果,至少也可以达到几百倍的效果)。 Map and Reduce的另外一大特色是它可以利用大批廉价的机器组成功能强大的server farm。最后,它 的容错性能异常出色,就算一个 server farm宕掉一半,整个fram依然能够运行。正是因为这个天才的认识,才有了Map and Reduce算法。借助该算法, Google几乎能无限地增加计算量,与日新月异的互联网应用一同成长。


算法并不局限于计算机和网络

举一个计算机领域外的例子:在高能物理研究方面,很多实验每秒钟都能几个TB的数据量。但因为处理能力和存储能力的不足,科学家不得不把绝大部分未 经处理的数据丢弃掉。可大家要知道,新元素的信息很有可能就藏在我们来不及处理的数据里面。同样的,在其他任何领域里,算法可以改变人类的生活。例如人类 基因的研究,就可能因为算法而发明新的医疗方式。在国家安全领域,有效的算法可能避免下一个911的发生。在气象方面,算法可以更好地预测未来天灾的发 生,以拯救生命。

所以,如果你把计算机的发展放到应用和数据飞速增长的大环境下,你一定会发现;算法的重要性不是在日益减小,而是在日益加强。

[ZZ]中国当代女大学生性行为实录

最近,某高等学府的校报在醒目位置对近来发生的一连串女大学生性越轨事件进行了曝光:

  一女大学生在深夜于学校的花园里与男友发生不正当关系,被保安人员发现……

  一女大学生私自与男友在校外租房同居被学校查出……

  两女大学生在市区某歌舞厅当“三陪女”被公安人员当场抓获……

  面对这一件件性越轨事件,人们愕然了:现在的女大学生是怎么了?

  作为校方,本来应该是“家丑不可外扬”的,但却大胆对其进行曝光,其中有学校的一片苦心,旨在提出警示,请广大师生乃至社会人士对这一问题进行思考。

  其实,大学生性越轨事件在各大高校均是一个普遍存在的问题。尽管校方明令禁止但偷吃“禁果”者仍大有人在,而且有愈演愈烈之势。为保护女大学生的身体健康,目前许多高校均相继安放了避孕套自动售卖机,应该说这是一种不得已而为之的做法。

  在过去的十年里发生了巨变。在20世纪90年代初,女大学生认为只有在相爱的两人之间才可能发生性关系,这也暗示了他们的关系将进一步发展,直到确立婚姻关系。而最近几年,某些女大学生虽然仍然认为两人如果相爱才会发生性关系,但并不意味着就一定和他结婚。也有的女大学生认为,即使两人不相爱,只要不是互相利用,也可以发生性关系。

  研究者曾对500名女大学生进行了为期4年的关于从处女到非处女转变的心理研究,发现女大学生体验过性活动的比例随年级递增。比例分别为:大一7%;大二13%;大三20%;大学四年级,约有1/4的女性经历过性生活体验。

  研究者认为,女大学生的性行为并不单纯地取决于年龄的大小。青春期性激素分泌,固然可以对某些行为的启动和追求起到生物学上的催化作用,如女子月经初潮的提早及男子青春期的提前、都加速了年轻人的性觉醒、然而,除此之外,一些与之相关的社会原因,也越来越受到了人们的重视,其在大学生性行为中起着推波助澜的作用。如:

  (1)商品经济的冲击,文学艺术(诸如电影、电视、录像、流行歌曲、刊物等)的潜移默化。

  (2)在20多年前,青年性活动那种引人注目的性别方面的显著差异,现在似乎不那么明显了。如同男性一样,女性也开始把自己的性需要看成是正当的,而且现代避孕方法的发展,也导致了女性性活动的增加。

  (3)社会对女性性活动越来越采取任其自然发展的态度,也为她们追求感官快乐抑或别的目的而采取的性行为大开方便之门。

  (4)20世纪80年代以来,权威遭到青年贬低的趋势扩展到了性的领域,抽去了高悬在女大学生头上的达摩克利斯之剑。

  除了上述生理原因、社会原因对当代女大学生的性行为的巨大影响之外,还有一个不可忽视的因素那就是心理原因,即导致其性行为的心理因素。女大学生正是在各种心态的诱使下,才越过了“雷池”,发生了各种各样的性越轨事件。

  显示河爱情的忠诚

  有的女生在恋爱过程中,对男友很满意,视对方为梦中的白马王于,对方却对她若即若离。姑娘生怕飞走了金凤凰,于是主动献出贞操,试图以最宝贵的圣地换取最忠诚的爱。

  “我怕失去了他。”某高校的一位女生说道,“我很爱他,我几乎是一见他就被他迷住了,但他总是犹豫不决。而且,他太理智,想得最多的不是我,而是以后的分配以及家庭是否干涉等等。可我一刻也离不开他。”这个女生根自信,“他是个老派男生,只要我们发生了性关系,他就会负起责任,再不会离开我了,因为如果那样他就会受到良心上的遣责而永远背上沉重的十字架。”

  其实,这位女生并没有领梧到爱的真谛。爱是相互吸引的,她即使用祭献式的真诚拴住了他的肉体,却不可能唤醒他心灵深处酣睡的爱。换一种角度讲,她最多只懂得爱的给予,却并没有弄明白爱的真意,得不到相应的回报。

  追求情欲的快乐

  现在,随着性科学的发展。性需要已被人们认为是正当的欢愉与渴求,奥古斯倍倍尔在他的《妇女和社会主义》中指出:“在人的所有自然需要中,继饮食的需要之后,最强烈的要算是性的需要了。”科马列克至是妙语惊人:“性交实际上就是输送一些爱情的细胞。”

  在20世纪80年代初,西方社会更是爆发了一场性解放和性自由运动,在许许多多的年轻人的深受其害,成了性的奴隶。

  由于受西方性解放思潮的影响,许多男女大学生也深受毒害、一味地追求感官的刺激,视神圣的性如儿戏,有的甚至走上犯罪的道路。

  一位女大学生在日记中如此写道:“我愿意,我要以此表达我的爱。只有他才能引起我感官的兴奋。在这种兴奋的欲流冲击下,我不能自持。我渴望同他结合,融为一体,在爱的催化下肉体的结合使我的幸福体验达到颠峰……我已经离不开他,渴望得到他的雨露润泽,惟有这样我才真正体会到生命的茁壮和温馨…… 没有性爱,我会变得疯狂。”

  短短的几页日记,一种唯性主义者的心态便赤裸裸地暴露在人们面前。

  为了个人的私欲

  性欲既可以使一个人高尚起来,也可以使一个人走向堕落的深渊。

  为了达到个人的私欲,有人不择手段、不顾廉耻献出自己的贞操。为了追求物质享受,满足吃喝玩乐等感官的需要,获得穿戴等时髦用品,有的女子也甘愿与别人发生性关系,用低级的卑鄙手段去赚来脸上肮脏的胭脂,一位来自贫穷老区的乡村姑娘在铁窗里洒下了悔恨的眼泪:“入校后不久,作为女大学生的自豪感已荡然无存。我的智商并不比城市女孩差,我缺少的只是物质,在装饰品上我感到差涩。我没有优越的家庭做后盾,在物欲横流的冲击下,我内心失去了平衡,我只能以自己仅有的青春肌肤来抗争,以此来换取城市姑娘所拥有的时髦和优越感。”

  而一位来自城市的家庭条件非常优越的女孩在悔过书中却如是说:“进入大学以后,家里人再也无法约束自己,可以随心所欲地大把花钱,可以尽情地吃喝玩乐。尽管家里给的钱并不少,却经不住如此的挥霍。刚开始,对于我频繁的经济赤字,家里尚能及时救急,再后来父母终于忍无可忍,对我实行限额供应,多一分都不给。然而平时花钱大手大脚惯了的我如何忍受得了这一招。于是在社会上‘姐们儿’的开导下,我开始开发自己的‘自然’资源,主动到歌舞厅做起了‘三陪 ’,从此陷进罪恶的泥潭而不能自拔。”

  更有一些女大学生为了获得保送研究生或留校任教的名额,不惜以自己的肉体作为交换条件,频频向自己的恩师奉献自己。

  避免孤独

  现代人的性格组成,为每位心理研究者所关注,而孤独则是让大家一直头痛的问题。观察表明,知识层次越高的人越易产生孤独的感觉。告别父母、背井离乡的女大学生,初来乍到,人地生疏,孤独之感油然而生,为了诽遣寂寞无聊的光阴,她们总是积极参加各种社团活动,试图他乡觅知音。

  有一位从小城镇去大连求学的女大学生小丽,刚入校时就体验到了没有什么朋友的孤独,于是便加入了摄影协会。是摄影活动把她引入了人生的圣地,她的孤独很快被热情所融化。会长是一位擅长摄影、善于交际的大四男生,在频繁的活动中,他渐与小丽混熟。一个学期末,摄影协会全体会员在餐馆会餐,嬉闹了半天,会长喝多了,小丽担心他会在半途出岔子,索性把他送回宿舍。小丽扶他回公寓躺下后准备离去,会长突然握住了小丽的手,一把将她拖了过去,强行占有了她。从此,会长常乘大家去看电影或自习之机,去小丽的宿舍对其提出肉体的要求,小丽如果拒绝就有被逐出摄协的可能。软弱的小丽害怕冷眼,更害怕与孤独为伍,只得半推半就,从此一发而不可收。

  不忍拂了男友的意

  随着恋爱的逐渐深入,双方的感情进一步加深,恋人间的身体接触也会由少到多,从起初的互相拉拉手,逐渐发展到拥抱、接吻及肉体的抚摸,再进一步,有的男性就会提出过分的要求——进行性的尝试,而女方可能怕拂了对方的意而有损于两人的恋爱关系,于是只好半推半就成全了自己的男友。

  某大学的学生小燕和小海,二人刚人校不久就谈上了恋爱,经过两年的风风雨雨,二人的感情已经相当深厚,小海已不满足于平时的拥抱亲吻,开始对小燕提出性的要求,起初小燕每次都是委婉地拒绝,可是搁不住男友的死磨烂缠,因为男友放言说,不按自己的要求去做,将和她分手,小燕终究不忍心拂了男友的意,深恐毁了二人的恋情、最后只好以身相许……

  逃避社会的压力

  自然赋予姑娘以美丽,而庸俗的社会压力却使她们迷失了本性,成了任人宰割的羔羊。

  一位即将大学毕业的女大学生在日记中写道:“我是家里的老么,是父母的掌上明珠,平时家人对我都十分溺爱。考上大学的时候,父母鼓励我要多交朋友,他们灌输给我的是年轻时可以挑人家,再过几年就换成人家挑我了。他们告诉我,现在大龄姑娘太多了,不要只顾学习,有了男朋友,也就有了依靠。一些长辈也对我说、找对象重要,这是一辈子的大事,要把握住时机。女孩子青春太短暂,再丑的女孩子只要年轻,有青春气息,就不愁没有人要;再漂亮的女孩,过了结婚年龄就讨人嫌了。我被周围的‘高论’潜移默化了。就这样,为结婚而找对象成了我大学四年必修的学分,无形中在我的心里产生了很重的压力。”

  “我是个文静而柔顺的姑娘,同学们都说我会成为标准的贤妻良母。追求我的男生虽然很多,可我最后选择了他,因为他风度翩翩,待人热情。我们的感情增进得很快,我俩的足迹踏遏了校园的每个角落。一个天气闷热的晚上,他邀我出去兜风。在一个僻静的郊外公园、他对我提出了性要求、我没有一点戒备之心,因为社会连同我的父母早已把我驯服。当我找到一个很爱的人,我便认定他是我未来的依靠,后来我还怀上了他的孩子。殊料他原来是一个衣冠禽兽,在占有了我的身体并玩腻之后,最后一脚把我端开……”

  作为个性成熟的标志

  在青春期到来后,女性和男性一样,要求与具有丰富的性知识和性经验的伙伴交往的愿望越来越强烈。有的姑娘觉得自己貌美绝伦,身心发育成熟,富于性感,该是展露风流的时候了,急于得到成熟异性的认同。

  某校一位大一女生与一男生交往了几个月,每当这位男生用赞赏的目光凝望着她时,她就觉得自己长大了,瓜熟蒂落,该是自由恋爱、自由结婚的时候了,大有“养兵千日,用兵一时”的感觉。于是她主动与这位男生发生了性关系,以此来证明自己的成熟和魅力。

  病态的交往手段

  在一夫一妻制社会中,夫妻性爱是十分神圣的行为,是夫妻感情的最高表现形式。然而,在现实生活中一些青年却奉行泛性主义,认为只要双方情愿,就可随意发生性关系。在这里,性行为已演变为禽兽的乱交行为,不仅无任何美可言,且简直是其丑无比。

  下面是一位失足女大学生的心理表白:

  我出生于一个教师家庭,父母日夜忙于工作,我们很少深谈。但父母的思想又非常保守与古板,固执而又严厉。平时我若与男孩子一起出门,父母规定我必须很早回来,并常由弟弟陪着出去。要想与心爱的男孩在一起,我就得编许多谎话才行。尽管父母严密监视,在15岁时,我还是设法与男朋友在公园里会了几次面:他吻我,抚摸我,他乐意这样,我也高兴这样。

  我本来打算在23岁以前不与人发生性关系,我想长大些再担负起这个责任。我可以允许男友拥抱我,亲吻我,甚至抚摸我,但决不轻易失去最后一道防线。奇怪的是大二那年,刚过了22岁生日,我去博物馆,在那里遇见了见多识广的年轻画家,我终于被他那美妙的绘画及博学多才的谈吐吸引了。虽然处女的羞涩妨碍了我对交际的好奇,但我还是平生第一次萌发了与人做爱的念头c实际的效果妙不可言我的交际面也从此拓宽了。从这时起,我知道肉欲并非罪孽,而是一种既可享受又可交往的手段,人们可以相爱,可以发生肉体关系,但不一定非得结婚。后来我又与一位年轻歌手相识、相爱,并频频做爱……在我心目中,与自己喜欢的男子发生性关系其实很平常,就和吃饭、撒尿一样简单。然而正是这种荒诞不经的观念最终导致我陷入了罪恶的深渊。

  报复和惩罚社会的一种手段

  瓦西列夫在《情爱论》中曾提到过这么一句话:“性欲是一股强大的力量,如果失去控制,它就可能成为社会的一种灾难。”

  如果说欺骗行为是人类两性关系的一大误区,那么性报复是这一误区的沉重沦落。生活的经验启示人们:当人的性爱目标受到阻碍或干扰的时候,就会产生一种强烈的情绪,我们权且称之为爱欲挫折吧。当受害者遭受某种欺骗而产生了损伤性刺激后,有可能造成心理崩溃,进而产生报复行为。在大学校园里,性报复事件时有发生,更奇怪的是,这些案子竟然被“复仇女神”所垄断,而且是通过某种心理机制的转变,把对某一异性的仇恨变成了对一切异性的仇视。这种变态心理的产生,往往是女性堕落的起点。

  一位女大学生如是说:“我之所以委身于男人,是因为我不仅需要男人,更需要寻找生活的支柱。”可以想象,一个把自身命运系在一个男人身上的女人,当她全部的理想在一夜之间化成泡影之后会陷于怎样的一种绝望之中。变态心理由此滋生了。这位女生被男友抛弃之后,便寻找奇特的报复行为来维持自己的心理平衡。她凭自己的花容月貌和风骚,出没于影院、公园、酒吧、舞会,主动搭汕,结交男朋友。

  她专门找那些夫妻感情不和的男子,撒网钓鱼:当对一男子捉弄够并厌烦时,她便把这种关系暴露给对方的妻子,给夫妻之间的伤口上再撤上一把盐。当有的男子不惜与妻子离婚向她求爱时,她却一改往日的温柔而翻脸不认人,一脚将其踢开,又去另觅新欢。有时,她还活动于几个男人中间,挑逗他们的感情,从几个男子的争风吃醋甚至大打出手中寻求莫大的刺激。

[ZZ]聚类搜索bbmao

聚类搜索bbmao

什么为你赢得风险投资?

什么为你赢得风险投资?

——专访 bbmao 网站执行董事、 CEO 朱明谦 , 副总裁李昌日

忽如一夜春风来 , 不经意间你就会发现 , 身边创业的朋友不知道什么时候又多了几个 , 这是一个创业的时代。 从“狠工作”改版为“创业故事”, 栏目该怎么做 , 盘算多日。 从刚创立的婴儿期 , 到站稳脚跟的少儿期 , 上市前的爆发式发展期 , 乃至上市后的平稳期。 我们想在今后几期依次展现一个阶段的创业的故事及其背后的智慧 , 而 Web2.0 无疑是能够提供所有创业阶段最充裕案例一个领域 , 这个领域造就了太多的传奇和成功。

临别 , 内向的新加坡人李昌日忍不住追 上来轻轻问道 :“你到底是怎么找到我们的 ?” “因为我在找新锐的 Web2.0 创业者啊。”看 着他一脸的真诚与 困 惑 , 忍不 住 浅 浅 一 笑。 的确 , 向周围的 人提起bbmao,估计没几个 人知道 , 尽管它创立仅一年多便 入选美 国著 名 风 险 投 资 杂 志《Red Herring》“2006 亚 洲百强”, 成为亚 洲互联网 领域最受投 资者 看好的 100 个企业之一。《Red Herring》被 投资家 誉为“ 硅谷圣经”,Google 和 eBay、 阿里巴巴等许多知名 IT 公司都曾在发展早期 被《Red Herring》的编辑们发现。

蜷缩在北京北部某个普通得不能再普通 的 居 民楼里 , 走进去 四面徒壁 ,13 个 年 轻人 外带他们的办公桌椅 , 一套两居的 房子撑 得 满满的 , 开会用的白板只能落脚暖气片上 , 这 就是 bbmao 的所在地。其实 , 由新加坡人朱 明谦和李昌 日共同创立的 bbmao, 成立仅几 个月便成功获得美国著名网站 MySpace.com 的创立者布莱特 · 格林斯潘的投资。在格林 斯潘手里 , 那个 MySpace.com 网站曾创下 3 年内实现注册用户过亿、成为全美最大网站、 网络流量达到 Google 的 2.5 倍、在半个月内 成为交友网站领先者的互联网神话。

除了幸运 ,bbmao 成功融资的背后还有 什么 ?

意外邂逅创业

对于在 硅谷有着优越生活的朱明谦来 说 , 选择在中国创业 , 纯属一次意外邂逅。

在美国 , 朱明谦就职于一家搜索技术的 领先公司 Verity。毕业于多 伦多大学并获取 了物理和计算机人工智能双硕士学位的朱明 谦 , 曾经写过及获得许多 跟搜索 和人工智能 有 关的论文和 专利。 搜索在他看来 ,“是一 件富 有 创造力并且有趣 的 事 情”。2003 年 , 因为受一个日本 朋友的感染 , 喜欢 旅游的朱 明谦计划用一年半时间游历世界 , 中国是其 中的一站。当他已经描绘好从中国往北直至 伊斯坦布尔的时候 , 一场突如其来的意外打 乱了他的一切 , 由于非典 , 边境全部被切断。 2003 年 6 月 , 朱明谦来到成都 , 成都人那种 “轻松、有趣、自由 , 可以做任何自己想做的 事情”的生活状态打动了他 , 从而选择驻留。 白天 , 他在成都的几所贵族学校当英语老师 , 晚上则继续在租赁的小屋里研究他在美国就 一直致力的聚类搜索技术。

第二年 , 朱明谦将自己的聚类技术报告 发给远在新加坡工作的老朋友李昌日。讨论 之后 , 两人 对创业一拍 即合 , 考虑到美 国已 经有先 入者 , 新加坡则 市 场有限 , 他们决 定 将该技术 运 用到中国 互联网市场。“当老师 的那段时间里 , 我已经深刻体会到中国互联 网市场的巨大潜力。中国互联网用户数量已 超 过 1.2 亿 , 是仅 次于美国 的全球第二大互联网国家。但这1.2 亿的网民还不到中国人口总量的10%”。

“之所以放弃美国的高薪, 是因为我看到很多自己可以做的事情, 比如对搜索现状的改 变。”总是一脸思索状的朱明谦说,“我在新加坡的一个合资公司做管理, 打工十几年之后工 作已经让我觉得过于平淡, 想有所改变。”安分的外表下, 李昌日一样有颗不安分的心。为了 注册审核方便, 公司的注册地被选在新加坡, 一个名为“Accumo”的公司就这样诞生了。

投资真正确定时

朱明谦永远也忘不了自己平生第一次融资、见天使投资人的情形, 那一次也可以说是他 平生遭遇的最大一次打击, 他也第一次品尝到怀疑自己的滋味。

Accumo 的定位是为企业提供软件服务, 做软件外包。为了拿到订单, 他们花钱在Google 上登载广告, 一个远在欧洲的企业通过互联网找到他们, 成了他们的第一个客户。不久, 网易在 为自己寻找搜索框软件的外包伙伴时,也把橄榄枝抛给了国内第一家拥有聚类技术的他们。在 为这两个客户提供服务的过程中, 他们的聚类技术不断得到改进, 朱明谦和李昌日的自信心更 强了。那时, 身在成都的朱明谦白天依然是英语老师, 晚上为客户做软件, 之余他有意识地开始 寻觅天使投资, 后来在朋友的介绍下,他得到一次去香港和一位天使投资人面谈的机会。

那是在香港某高级宾馆。当把长达几十页的商业计划书递给对方之后, 朱明谦便直直站在 原地, 期盼着对方看完之后的愉快洽谈, 看似平静的外表之下是早已澎湃的心。结果却出乎意料, “等来的是长达数小时的无情批驳, 对方认为做企业软件利润薄, 没有投资价值, 更何况做OEM 接触不到真正的客户, 没有前途。”他事后都想不起来自己是如何走出那个房间的。“后来冷静 下来, 就有完全不一样的感觉, 反思对方当时所说的话, 思考自己存在的不足, 对创业方向重 新度量。”朱明谦说,“现在想想, 如果没有第一次融资的失败, 我们后来也不会那么快就转 到网站这方面来, 顺利得到格林斯潘的投资。”

拉不到投资, 朱明谦过了一段非常艰苦的日子, 他给自己开的工资很低, 除了一日三餐 的粗茶淡饭和房租、水电外, 几乎都不怎么花钱。“有一次在街上看到卖桃子的, 都记不得自 己有多长时间没吃水果了, 上前只捡了两个桃子, 结果卖桃子的嫌少不卖给我。”朱明谦不无 伤感地悠悠回忆着。

2004 年8 月的一天晚上,朱明谦照常上完英语课回到租赁的小屋, 打开邮箱意外发现 一封来自美国的莫名邮件,“发邮件的人就是myspace 的创始人格林斯潘。在邮件内他提及, 通过互联网, 得知我在聚合搜索方面的一些构想, 想进一步了解了解”。之后的半个月里, 他们电话沟通了好多次, 沟通中, 朱明谦发现 对方的兴趣点在互联网上, 基于上一次和天 使投资人接触的经验, 他学会了灵活变通, 及时捕捉对方的关注点, 调整自己的商业计 划书, “后来我们在香港见了面, 只有10 分钟, 他就决定投资。”

朱明谦他们并没有马上拿到钱, 但这 并没有影响他们的积极性, 返回成都后很快 按照计划将办公地点搬到了北京, 更名为 bbmao( 北京比比猫网络技术有限公司), 直到 八个月之后的2005 年底, 第一笔钱才到位。 那八个月里, 公司从两人也迅速扩充到五个 人, 格林斯潘不断地分别打电话给他们所有 人, 包括当时刚刚加入bbmao 不久的美国人 Bill, 现在的CFO。“电话里都是询问我们工作 的进展情况。在那几个月里, 我们发布了软件 的测试版, 网站主要的支柱性功能基本成型。 并且和香港一个公益组织谈成合作, 只要成为 我们的注册用户, 用户的名字便会以公益捐赠 者的身份出现在该组织的网站上。虽然用户 总量当时还很小, 但每天都在增加。”

“我想, 格林斯潘正是看到我们切切实实 在一步步按照我们的商业计划书工作, 他才 真正确定了投资。”李昌日补充道。bbmao 成为一个提供社会化搜索引擎的网站, 其根 本是发挥Web2.0 的内核, 个人应用, 靠用 户改变搜索结果。曾经听人说,Google 就 通过搜索结果的点击改变搜索结果的排序, 使搜索结果更合理。bbmao 则通过聚类技 术和关注别人的相关收藏来改善搜索结果。 2005 年底, 格林斯潘完成对bbmao.com 的 注资。得到了第一笔投资后,bbmao 一切变 得很顺利, 现在朱明谦每天都会接到来自各 个国家不同风险投资机构邀请商谈投资的电 话和邮件。“也许有一天,bbmao 也可以像 myspace 一样, 得到所有人的认同, 并改变 所有人的网上生活。”

创业总是与执著相关的故事。创业不一 定成为富豪, 但执著一定能成就梦想。

心理测试: 现在当老板你够不够格?

你也想创业? 创业充满了诱惑, 但并非每个人都适合走这条路。美国创业协会设计了一份测试题, 假如你正想着自己“单挑”, 不妨抽出两三分钟先到我们的www.staffers.com 做做这份测试题.

Mentor: 第一次去见风险投资商

作者/ 周鸿袆

与风险投资商的沟通绝对不会是一个顺利的过程,“投”与“不投”都是很正常的事情。原因很简单, 小公司所做的事情必然有其超前性, 否则也没有什么商业机会可言, 面对一个超前的事物, 你无法要求所有 的人都赞同你的想法, 十个人里有两个愿意和你谈一谈, 就已经非常不错的了。俗话说“挑货才是买货人”, 最重要的是坚持, 在不断被挑战的过程中不断矫正自己的想法、打磨自己的商业模式。

投资商第一次见面时最爱问三个问题: 你的核心价值是什么? 能给客户带来什么价值? 为什么你能做成, 你的核心竞争力在哪里? 这些问题创业者都要思考清楚, 并懂得用精练的语言去表达。很多商务模式并不是 创业者的首创, 比如我现在每天都能接到一两份关于“城市生活指南”类的计划书。既然大家都想做这个事, 那么你有什么绝招? 你为什么觉得能比别人做得好? 对这些问题的回答才是对核心价值的表述。关于“客 户价值”的问题, 任何产品, 只有给别人带来价值, 别人才会使用。有人对此没想明白, 反复说他自己对这 个东西如何沉迷、喜爱, 这是没有说服力的。 重要的是如何把目标分解, 哪怕目标并不那么宏伟, 但让人觉 得你能一步一步地靠近目标。靠近目标的能力就是创业者的核心竞争力。当然, 除非创业者很有背景、有成功记录, 或者有人推荐, 否则风险投资商还是希望先看到文字资料。

2007年4月15日星期日

[ZZ]一个LINUX狂人的语录

"我已经半年没有使用 Windows 的方式工作了。Linux 高效的完成了我所有的工作。GNU/Linux 不是每个人都想用的。如果你只需要处理一般的事务,打游戏,那么你不需要了解下面这些了。
我不是一个狂热的自由软件份子,虽然我很喜欢自由软件。这篇文章也不是用来推行自由软件运动的,虽然我觉得自由软件运动是非常好的。
这篇文章也不是用来比较 Linux 和 Windows 内核效率,文件系统,网络服务的。我现在是作为一个用户而不是一个开发者来说话的,我们的讨论是基于操作,应用层面的。是为了告诉大学里还不了解,或者不 理解UNIX 的科学工作者和大学生,UNIX 比 Windows 更适合用于科学研究工作,请大家理解 UNIX 的工作方式,不要用 Windows 的标准来要求 Linux,而要用一个科学工作者的标准来要求自己,用UNIX 的思想来武装自己。
我显然是反对在大学,特别是理工科专业推广 Windows 的。我也反对在对"娃娃"们的计算机启蒙教育中使用 Windows。因为 Windows 不论从技术上,经济上,思想风格上都是与我们培养高科技人才的目标格格不入的。Windows 的流行属于历史遗留问题,爷爷一级的人当然已经不可救药,但是我们不应该让下一代继续走上歧途。
UNIX 不是计算机专家的专利
当我建议一些非计算机专业的人用 Linux 的时候,很多人说:"UNIX 是计算机系的人用的,我们不能理解。" "UNIX 是男孩用的,我们女孩不用。"
但是其实世界上的大多数科学家和工程师几乎用的都是 UNIX 作为他们的电脑工具。就因为它简单,可靠,稳定,强大,有趣。甚至很多时候 UNIX 就是唯一的选择。
你说:"我们都会用 UNIX 的话,你们计算机专业的人还用来干什么?"
很容幸的告诉你,计算机专业的有一部分人就是专门为你们提供这样强大而方便的计算机工具的。如果他们制造的工具只有自己会用的话,那这个工具还有什么用?
理解 GNU/Linux 不要用 Windows 的标准来要求 Linux。
由于GNU/Linux这个词太长,下面如果没有特别指明,"Linux"就是指GNU/Linux"。
在这个年代,恐怕没有人需要我来介绍 Linux 是什么了吧?如果你觉得"Linux 只不过是跟 DOS 差不多的东西",那请问问你旁边的Linux 用户,Linux 到底是什么?
那为什么我还要写一篇这样的文章?因为,我发现还有很多人不不理解 Linux 和 UNIX,虽然他们也在用它,但是他们有时会问:"为什么 Linux 不能像 Windows 那样 ……?","怎么Redhat Linux不能 mount NTFS 分区!","Linux 下用什么整理硬盘?","什么时候OpenOffice才能完全兼容Word文件啊?","现在还有什么Windows能干的事情Linux干不了的? "……
他们有40G的硬盘,却只为 Linux 分配了2G空间,有时还抱怨"这个东西怎么占这么多硬盘!" 似乎 Windows该占用大部分硬盘。他们把重要的数据装在Windows的分区,似乎信不过Linux。他们总是到处寻找新奇的,好看的GUI程序,对命令 行的东西一概不屑一顾。他们对Drag&Drop,菜单配置,自动升级非常感兴趣。他们如果找到一个很像 Windows 程序的 Linux 程序,一定会很高兴的说:"哈哈!Linux 也能……了!"如果Linux在某种测试中胜过Windows,他们会高兴得跳起来。他们没有办法用Linux 解决问题的时候,甚至用Wine来运行Windows程序。有时实在没办法,只好重起到Windows,或者干脆省得麻烦,在 Windows 下装一个 VMWare 虚拟一个 Linux 玩。
你如果出现了上面的情况,说明你的思想受到了 Windows 的某种潜移默化的影响和误导。你没有能够从本质上理解存在于 Linux 身上的 UNIX 思想。你支持 Linux,你喜欢 Linux,你能从中感觉到快乐,这非常好。你现在只需要明白的是:Linux 从来就不是一个玩具,它是天才UNIX的后代。UNIX 是自晶体管发明以来最伟大的发明,它从诞生那一天开始就比 Windows 的设计出色。
你要体会什么叫做"设计",一个糟糕的设计并不是到后来缝缝补补就可以变好的,而一个出色的设计,不但可以以不变应万变,而且可以影响到后来者。一个出色 的设计配上一个出色的实现,那就是非常出色的发明。Linux 就是这样的一个出色的发明。Linux 并不需要追赶 Windows,也不需要打垮微软。它的最终目标是改变整个计算机世界,还人们自由,给人们乐趣和方便。
Unix 是简单的,你不需要成为一个天才也能理解这种简单。
UNIX的设计者 Dennis Ritchie 说:"Unix is simple. It just takes a genius to understand its simplicity." 但是我不这么认为,因为我不是一个天才,但是我却勇敢的把 Windows 完全删除掉,遇到不明白的事情的时候努力用 UNIX 的方式去解决,而不是寻求 Windows 的帮助。现在我体会到了 UNIX 的思想和好处,我可以用比 Windows 高效几倍的效率工作。因为我相信这样的信念:"Windows 能办到的事 Linux 一定能办到,而且办的更好。"
这小节开头的话应该改成:"Unix 是简单的,你不需要成为一个天才或是计算机专家。但是在这个冲斥着 Windows 错误观念的世界,你需要信念和勇气才能理解它的简单。"
我下面就告诉你一些我理解到的东西。首先,你要知道的是微软在国际科学领域是根本没有地位的。
微软的地位
微软的名声在欧洲和美国的大学里,特别是在计算机系里之坏,大家可能有所耳闻。我认识的 MIT,Stanford 的教授,贝尔实验室的专家,甚至一个欧洲小国的高中计算机老师都绝口不提微软的名字。在他们眼里,微软只是一个没有真技术,专靠在落后国家商业宣传和垄断 经营的小公司。这个"小"并不是说它人少,钱少,而是说它先进技术少。
我上次和王益合作写了一个算法演示程序,那个算法是贝尔实验室一位科学家Steven Fortune很天才的发明,为了程序能够被身边大多数人使用,我们选择了 VC+MFC 作为平台。我在分析算法时还得到 Fortune 很热情的鼓励,寄给我一份资料,还多次回信耐心的给我讲解了很多细节。但是程序完成之后,我把样品发给 Fortune,他回信说:"对不起。我机器上没有 MFC。" 话说的很客气,但是我已经感觉到了他对 Windows的不屑。然后我把 MFC 静态编译进程序再发给他,他就没有再回信了。他显然不是瞧不起我,而是确实有难处。
你能感觉到这位科学家对微软和 Windows 是什么态度了吧?不是反感,而是他心里根本没有 Windows 这个东西!微软在高科技领域没有发展,那么它怎么生存呢?到发展中国家去发展一下,他们的人民还对电脑一无所知,我说不定甚至可以打入大学的计算机系呢。 我送他们软件,我捐钱盖大楼,我出钱找图灵奖获得者来演讲,让他们觉得我们都是科学家!
好了,现在全国的大学包括清华,几乎所有人机器必装盗版 Win2000,Office XP,学校的选课系统是非IE不能正确浏览,论文用 Word 编辑,演示用ppt做,email 的通知附件是 doc 文件,你不用 Word 打不开,连 863 项目都用 VC 写程序了。我很久以前就看到一份报纸说,"微软为什么不严厉打击盗版?"
这篇文章说,微软非但不打击中国的盗版行为,而且有放任之趋势。放长线吊大鱼,"以后我要你们加倍的来还我!" 确实如此,它的目的快实现了。
Windows 笼罩下的中国计算机教育
说句丢脸的话,比尔盖茨很久以前是我的偶像……
在中国,比尔盖茨被很多人奉为神圣,"少年电脑天才",甚至有的人提到他的名字就做出"抱拳对天"的姿势。很多人谈到微软的"新技术","高科技" 都是眉飞色舞。各种"VC编程圣经","深入了解 Visual C++"之类的书,在开头几页都会出现非常肉麻的字眼,"在那团团的混沌中,一个开天辟地的精灵,Windows 1.0,诞生了……"
微软的软件被这么多人盗用,那么人们是怎样使用这些盗版程序的呢?先看看电脑培训班,教的都是一些 DOS 命令,打字,Windows 基本操作,Word 文档处理,PowerPoint,高级班可能有 Excel,Access…… 参加各种微软认证考试,MCSE,MSDE 的人络绎不绝。考试辅导班都贴出了"280元,考过为止"之类的字样。考试参考资料更是昂贵,有些电脑书店整整两书架都是"Microsoft Press"的东西。我有个同学参加认证考试,每门考试都要200多元。而且你一次考不过可以再考,又要交钱。他后来还津津乐道跟我说,看我,花了 XXXX(一个四位数)元考过了微软认证,得到一张比尔盖茨亲笔签名的证书和价值6000元的 Windows XP 内部发行版。
"电脑要从娃娃抓起",我们再来看看娃娃们学的是什么。大部分家长给孩子买了电脑之后,他们首先就会装一个盗版的 Windows,然后买来盗版的游戏开始玩。如果哪个孩子会用 Delphi 编程序,那可不得了。报社记者,电视台争相报导,说,某某学校的初中生某某,在别人都还在玩电脑游戏这种"初级阶段"的时候就已经用 Delphi 写程序了。镜头还瞄准了他显示器上面的像框中的比尔盖茨头像!
我刚进入大学计算机系时还不懂得什么是操作系统,因为我以前只用过"中华学习机"。看到新入学的同学们各个谈论的都是 "Windows 95","VC"……
我简直觉得我落后了好几十年一样,整个一土人,根本跟他们答不上话。好不容易找到一个比较熟的同学问了一下:"你们天天谈论的瘟95是什么啊?"答:"win95就是一个操作系统,跟DOS是一类。""朵死是什么?"
"你连DOS都不知道是什么?别在计算机系混了。" 学校上课当然不讲VC编程之类的东西,但是上 Pascal 的老师有一次就说:"嗨,我们学校真是落后。现在别人都用 C, C++,甚至 VC 了,我们还在讲
Pascal。不知道什么时候才能有VC课啊。你们出去也是要用VC的,只好自学了。"
于是,有些同学很多时候上课都捧着一本很重的"Windows 编程大全"之类的书,根本没有听课。吃饭时就念念有词的跟我说,"代码的优化是无止境的","匈牙利命名法真是伟大的发明" ……
这就是中国很多大学计算机系的情况。
感觉到无知了?这不是偶然的,而是微软长久以来埋下的伏笔。它要让无知的大家都把它奉为神圣,它要让支持UNIX,Xwindow的人一旦说 UNIX 好,Xwindow 好的时候,都被一群人围着说教:"这个 Windows 也能做到","你对 Windows 有偏见","微软才是主流啊","你敢瞧不起 win2k?",".NET 就是世界潮流","微软的毕竟是新技术","有钱就是有技术"……
甚至在一番论战比较后败下来还是要说:"Windows 性能差点,但是易用性强","Windows 是老百姓用的,要求别那么?quot;,"微软那么有钱,以后想超过 UNIX 还不容易吗?"……
发达国家的计算机教育
我前段时间在 USENET 发文问有关 Scheme 语言的问题时,认识了一位丹麦人。他解决了我所有的问题,并且建议我阅读一些很"深奥"的有关程序语言语法,文法的书,他告诉我很多网站可以学习 LISP,Scheme,人工智能,算法。他叫我看 Jonathan Rees 的论文 "Syntactic Closures"。他还打包给我寄过来一份 MIT 的 "How to Design Programs"。他说他在自己的 PC 机上装的是 Linux,他用 Emacs 编辑,运行Scheme 程序。他对 Emacs 的了解和爱好真是使人惊讶。他大学本科毕业时做的毕业设计是一个 Scheme 解释器。这对于我来说是望尘末及了。
他是那么的不厌其烦,我的每一个问题他都详细的回答。我有时都觉得过于详细了,怎么这么耐心啊?我觉得他似乎是我的高中老师。他是什么样的人呢?我好奇的打听了他的情况。原来,他是丹麦一所普通高中的计算机老师。
他说他在高中里讲授程序设计和算法,计算机语言文法。他说用 Scheme,他的学生不用再为内存泄漏等程序语言本身的问题而烦恼,而专注于问题和算法本身。有利于培养学生解决问题的能力,特别是用计算机解决数学问题的能力。
天哪!为什么欧洲出现那么多数学家,几何学家?你看看别人重视的是什么!我们的计算机教育如果继续这样下去,只会沿着弯路越走越远!
微软和它的朋友们的如意算盘
下面来看看微软的收入是怎么来的。首先,Windows 98系列操作系统,一个就是100多美元,每次升级又是几乎同样的价钱。Windows NT 还要贵几倍,而且有用户数目限制,5个用户的,10个用户的…… 以后如果要增加用户数目还要按比例付钱。
花了如此多钱买来的操作系统就能用了吗?它竟然连压缩程序都没有提供!你装上Windows 之后一般第一件事就是去下载一个 WinZip 吧,"只要 29 美元"。Windows会中病毒啊,马上花 70 美元买一个 Norton AntiVirus 吧。还有黑客呢?再买一个Norton Internet Security 好了,100 美元。系统需要优化,磁盘需要整理,买一个Norton System Works 是你最佳的解决方案,100美元。
可是你现在还是不能干正事啊!你想要一个 Word, PowerPoint?那就买一套 Office XP 吧,一起买便宜些,$459.90。
那些程序不会用啊!那些菜单怎么设置,到底有什么功能啊?看"帮助"也学不会。买本书看看吧,我推荐"Special Edition Using Microsoft Office XP",不贵,$27.99。这本书里面大部分是屏幕抓图,还是买一本旧的比较划算,$17.85。
你如果只是当个秘书,上面的差不多还凑合了。可是你有更高的追求,你想成为 Windows程序员。首先买一个 Visual Studio.NET 吧,要不然怎么编译程序。$494.95。
为了紧跟微软动向,世界潮流,不能不注册个 MSDN 什么的吧?这个贵一点,不过物有所值啊,$2,799。
嗯,你现在已经是上层阶级,白领人士了。你现在可以像这样"自由"的,"安全"的生活了。
为什么要反对使用 Windows
很多人都说不应该完全否定 Window,Windows 也有它的长处。不应该骂微软。

对。Windows 容易操作,适合普通用户。如果微软把它自己定位在 P&G,Philips
那样的地位,能够给我们的百姓提供周到的,完善的,价廉物美的服务。那我肯定是很喜欢它的。但是从上面的种种情况说明,微软是一个野心极大的国际垄断组织!它的产品没有一个是不出问题的:Windows
不稳定,容易中病毒,而微软不为大家免费提供杀毒软件。我就是要让你们花钱买我的朋友 Symantec 的杀毒软件,谁叫你们已经上了我的贼船?这叫什么售后服务啊!
你买来微软的程序,安装的时候一般都有一个协议,说:"由于微软的程序造成你的数据损坏或丢失,微软概不负责。"
我想很多人肯定觉得这个不合理,不想按那个 "I accept"。但是你的软件买都买来了,钱都花了,现在一按 "I decline",安装程序马上就会退出。你只好被迫点击了 "I accept"!这不是不平等条约吗?
我已经目睹了好几个朋友的文档被 Microsoft Word 损坏,有的是编辑了十多天的30多页的论文,有的是费了很大工夫做出来的个人简历,那个朋友为此失去了到自己向往的P&G 工作的机会。就在他要投简历的前一个晚上,就在那一瞬间……
不知道他痛哭的时候有没有想起要投诉微软,可是谁叫我们用的都是盗版呢,况且你还点击了 "I accept"。
微软仗势已经占有大部分PC市场,制定不符合国际标准的"微软的标准",以不合理的方式压制其它公司的软件,这个问题已经在美国司法部闹了很久了。他甚至 在 Windows系列操作系统中放置能够通过网络泄漏用户信息的代码,以至于 Windows 刚进入澳大利亚时被澳大利亚政府禁止使用。
有些人说:"微软毕竟开创了一个历史,造就了今天的 IT 行业。"
但是,如果没有微软,我们今天早就用上非常稳定,非常可靠,非常方便,非常"傻瓜"的软件了!微软是阻挡信息技术发展的罪魁祸首。
微软的程序的工作方式(注意,我只是说操作方式,病毒的事情另外算)确实适合于一般家庭,上上网,发发邮件,打打游戏都不错。可是微软却要把自己包装成什 么"高科技"企业,要在世界各地设置"研究院",在大学计算机系赠送不适合用于科研的 Windows产品,甚至出钱请图灵奖得主来中国畅谈"二十一世纪的计算",还在大会上宣传自己的 .NET 技术。非要把别人认为自己是科学的,自己是领导世界高科技的。但是呢?它什么高科技也没有。欧洲,美国,哪一个关键部门在用微软的东西?NASA? DOE? CERN?你仔细想一想,微软的程序对人类到底有什么重大作用?
什么是 Windows 能干而 Linux 干不了的事情?---
"Windows 能干而 Linux 干不了的事情,那就是不需要干的事情。"
有个朋友看我半年没有用 Windows,有时就会问我:"你只用 Linux,有没有发现有些Windows 能处理的事情 Linux 干不了?"---
我回答说:"Windows 能干而 Linux 干不了的事情,那就是不需要干的事情。"
Windows 能做的有益的事情 Linux 都能做---
Windows 下的某些功能确实是我们需要的,那么 Linux 的开发者们和用户也需要这种功能,他们就会去实现这种功能,而且比 Windows 的方式好得多。由于大多数科学家,工程师用的都是 Linux 或者某种商业 UNIX, 所以几乎所有商业的科学工程程序,比如Matlab, Mathematica, AutoCAD, Candence的,Synopsys的,Avant! 的……全都是先有UNIX 的版本(包括Linux),然后再考虑移植给 Windows,甚至根本不移植给Windows,因为 Windows 的机器一般没有足够的能力运行这样的程序。你不要以为只有Windows 才有 PSpice, UNIX 的 HSpice 要好得多,而且可以运行在大型主机上。当然它们不是免费的,但是它们值那个价钱。

[ZZ]linux下的C语言开发要学些什么

原帖http://blog.csdn.net/plusboy/archive/2007/01/17/1485255.aspx

linux下的C语言开发要学些什么

虽 然在linux下写程序也有5、6年了,但是这几年来一直都没有想过在linux下开发要学习些什么东西,2006年年初离开了原来的公司,进入现在的公 司做linux平台下的集群开发,linux下的C编程便成了每天工作的重点。前两天回到母校的BBS上转了一下,看到一些师弟们在问,学完学校的C语言 教科书后,怎么进一步学习C语言开发。现在我就以我这几年的经验谈谈在linux下做C语言开发都要学些什么东西吧,希望对初学者能起到一些抛砖引玉的作 用。

一、工具的使用

1、学会使用vim/emacs,vim/emacs是linux下最常用的源码编辑具,不光要学会用它们编辑源码,还要学会用它们进行查找、定位、替换等。新手的话推荐使用vim,这也是我目前使用的文本编辑器。vim有一个中文在线手册http://vcd.gro.clinux.org

2、学会makefile文件的编写规则,并结合使用工具aclocal、autoconf和automake生成makefile文件。

3、掌握gcc和gdb的基本用法。掌握gcc的用法对于构建一个软件包很有益处,当软件包包含的文件比较多的时候,你还能用gcc把它手动编译出来,你就会对软件包中各个文件间的依赖关系有一个清晰的了解。

4、掌握svn/cvs的基本用法。这是linux,也是开源社区最常用的版本管理系统。可以去试着参加sourceforge上的一些开源项目。svn有一个中文网站:http://www.subversion.org.cn对svn进行介绍。

二、linux/unix系统调用与标准C库

系统调用应用软件与操作系统的接口,其重要性自然不用说,一定要掌握。推荐学习资料为steven先生的UNIX环境高级编程(简称APUE)。

三、库的学习

无论是在哪个平台做软件开发,对于库的学习都很重要,linux下的开发库很多,我主要介绍一下我常常用到的一些库。

1、glib库
glib 库是gtk+和gnome的基础库,并具是跨平台的,在linux、unix和windows下都可以用。glib库对于linux平台开发的影响就像 MFC对windows平台开发的影响一样,很多开源项目都大量的使用了glib库,包括gimp、gnome、gaim、evolution和 linux下的集群软件heartbeat。因为glib库自带有基本的数据结构实现,所以在学习glib库的时候可以顺便学习一下基本的数据结构(包括 链表、树、队列和hash表)。glib库也有一个在线手册,网址是http://developer.gnome.org/doc/API/glib/index.html
http://developer.gnome.org/doc/API/2.0/glib/index.html

2、libxml库
libxml是linux平台下解析XML文件的一个基础库,现在很多实用软件都用XML格式的配置文件,所以也有必要学习一下。libxml的网站是http://xmlsoft.org/index.html

3、readline库
readline 库是bash shell用的库,如果要开发命令行程序,那么使用readline库可以减少很多工作量,比如bash里的命令行自动补全,在readline里就已经 有实现,当然你也可以用自己的实现替代库的行为。readline库有很多网站介绍的,只要google一下readline就可以找到一堆了。

4、curses库
curses 库以前是vi程序的一部分,后来从vi里提取出来成为一个独立的库。curses库对于编写终端相关的程序特别有用,比如要在终端某一行某一列定位输出, 改变终端字体的颜色和终端模式。linux下的curses库用的是GNU实现的ncurses(new curses的意思)。推荐一个curses学习网站http://web.cs.mun.ca/~rod/ncurses/ncurses.html


5、gtk+和KDE库

这两个库是开发GUI应用程序的基础库,现在linux下的大部份GUI程序都是基于这两个库开发的,对于它们 的学习也是很有必要的。


四、网络的学习

网络这个东西太宽了,推荐学习资料steven先生的UNIX网络编程(简称UNP)和TCP/IP协议详解,更进一步的话可以学习使用libnet编写网络程序。

[ZZ]男的依然是禽兽,女的却已禽兽不如了

下面这些疯话不是用来被赞同的而是用来被记忆的,等到时机成熟的时候会有一些启发。并且,小弟诚心的祝兄弟们lucky到永远也等不到时机成熟。
  
  和女的讨论问题通常有几个特点:
  1。举例而不是比例。
  2。提出新的疑问之前基本不先回答前面对方提出的问题。
  3。说别人的想法她不“了解”,也不愿猜测,所以没法讨论共性问题。
  4。说你假设的不真实。
  5。谈论谈论话题的人而不是话题本身。
  6。用你的母亲做例子谈论问题。
  
  什么是“安全感”?就是时刻可以不讲理的权利。
  
  对于雌性动物,生理结构决定了它们力气小,必需要依附于雄性动物才能安全,什么都不能改变这点。人类社会中,女人力气也小,可是科技改变了生存模式,只要有钱也能安全了,所以,越是给女人钱,女人就越不需要依附男人,就越敢于表现压抑了2000年的本质。
  
  对于雌性动物,破处和生孩子之间的间隔很短,破处之前纯洁,生孩子之后母性,总有可取之处。可我们发明了避孕,女人可以处于中间状态很长时间,即失去了纯洁又没找到母性,修养上越来越差,没有东西能平衡男人的牺牲了。总之,男人依然是禽兽,女人却禽兽不如了。
  
  若要雌性动物服从,是需要外力压迫的,没有外力压迫,她们就不会敢受到威胁,就会显出本质。从人类历史上看,这些外力压迫只有3种,1是缺乏体力保证生存,2是社会礼教约束,3是金钱制约。兄弟们,如果你发现女友在这3点上都没有受到压迫,那么只能祝你lucky了。
  
   男女开始时都骗了对方。男的说会一万年,女的没说自己的修养水平会下降。若是男的不说一万年女的就不给生殖器,而生理结构决定了男的比女的更早需要对方 的生殖器(想想寡妇为何更苦)。也就是说,开始时,女的要挟了男的。后来,男的后悔了,女的坚持要兑现那一万年,不然就闹,即使在后期女的自身水平的下降 超出了任何人的想象。
  
  女人靠什么生存?靠你以为她们(还)天真。第一步骗一个她认为最有发展前景的男的,第二步结婚,然后不断闹 他更上一层楼。这一切都是在感情的名义下用生殖器来要挟着完成的。男人说了实话,女人会愤怒但不会惊讶;女人说了实话,男人被吓死。女人的幸福全部建立在 对自己真实想法的伪装上。
  
  显然,现在还不是谈论男女真正平等的时候,因为即使单从感情上来看,男的还不具备把女的当成兄弟的能 力,还是在对女的谄媚、纵容和美化;女的从来都没有具备过把男的当成姐妹的能力,她们始终努力催促男的去满足自己各种类型的要求而不明示凭啥。兄弟们,你 们记住,女的的爱,不是只为钱,是为了你能始终努力去满足她提出的各种类型的要求。所以,你很容易发现她们不记过去,从不牺牲,永不满足,为方便记忆,可 称为“三不”。
  
  妇女同志的经济独立,不应仅仅是不依靠某一个男人的帮助,而应是不依靠所有男人的帮助,包括老头。
  
   这就是女人平等的阴谋,需要权利的时候她们说应平等,说到义务的时候她们说自己弱小。因为她们知道,真正的平等对女人来说是死路一条。女人,若不需要被 照顾,请明示;若需要被照顾,请服从到能平衡照顾。又需要照顾又不服从到平衡又不明示的,就是骗子,骗子不配被尊重,不配谈平等,只配被将计就计。
  
  妇女解放了50年,妇女被压迫了2000年,难道2000年的智慧实践探索经验教训比不上50年的?难道2000年中的人都是傻子?今人把古人为什么那么做的原因给忘了,那就让我们再来一次吧。
  
   从禽兽上来讲,公的都照顾母的到什么程度呢?照顾到母的能生出孩子,也就是说,母的吃饱穿暖后,与生孩子无关的其他要求,公的是置之不理的。公猴也到处 播种,母猴也没像女人那样闹;母猴也没有要求有房有车无贷还要赔笑一生,相对于女人,母猴基本上算是清纯的。因为母猴受到了体力上的生存威胁。兄弟们之所 以仍然需要找女的而不是母猴是因为与母猴语言不通,这点比不上有些姐妹,语言不通也能“爱”。有些大姐说,对配偶之外的性好奇女的也有。可强度相同么?你 也从12 岁到80岁都愿意为****而出精力出钱么?你也愿意为****陪70年的笑脸么?再说,女的用以诱惑男的的东西怎么来的?男的用以讨好女的的东西怎么来 的?
  
  姐妹们,找一张纸,列个对照表,你认为的,你对男的有什么用处vs男的对你有什么用处;再列一张,母猴如何要求公猴vs你如何要求他的,你的修养就能自我升华了。千万不要相信你爹妈的话,如果按照他们的说法做,你爹年轻时都不会找你。
  
   转,“这世界,女人寻找"好男人",男人寻找"好女人"。男人和女人在寻寻觅觅中,往往因为缺乏洞察力而结婚,因为缺乏忍耐力而离婚,因为缺乏记忆力而 再婚。男人的错误在于他一心想娶一个十全十美的女人。女人的错误在于她一心想嫁一个百分之百爱她的男人。结果是男人和女人一起失望。所以,男人和女人终其 一生就是一场天长地久的寻觅。”
  
  请教一下,若你有一儿一女,社会的两性规则由你定,但是这一个规则会作用于所有人的同龄儿女,你会怎样定这个规则?
   比如,你不能说,儿子可以多找几个女朋友,女儿却最好第一次就找到最好的;你也不能说儿子取个温顺的媳妇,女儿却也要嫁个听话的老公。这些都是双重标 准。现在需要探讨的是一个标准,你儿子用这个标准找媳妇,你女儿也用同样的标准找老公,别人的子女也是用同样的标准找。我的回答是:主动努力帮助对方增加 幸福,程度要大致等于历史上你从对方的努力中得到的幸福。
  
  根源在于利用自己的身体需不需要规则来约束,若是需要约束,女的就不要用生殖器换取与性快感无关的东西;若不需要约束,男的就应该可以凭力气大****。哪个更好些不辨自明。
  
   女人有源于生理的本质,男的也有,而且都可最终归于贪婪和自大。但区别在于客观世界会用困难直接教训男的的贪婪和自大而使他们改变,可女的是通过欺骗的 使用男的来满足她们的贪婪,支撑她们的自大的,她们感受不到直接来自客观世界的困难所以没有办法自我改变。更可怕的是,长久处于这样的环境使她们丧失了讲 客观道理的能力。理论上,只有女儿国才能使她们回到客观世界中,所以没有女人自愿去女儿国。
  
  这确实是个两难的选择,兄弟们,一部分女人在早期都不是故意骗的,单纯的女性本质对男性本质并没有什么对错或高下,只是目前所观察到的女性本质更不利于社会的发展。
   1:如果你选择了纵容这些女性本质,好像饮鸠止渴,无疑你会在开始阶段得到更多的机会,如果你更换得频繁一些,或许也会躲过这些本质的负面在这个女的身 上发作的阶段,但从长远上和统计上来看,你会发现你的选择面越来越窄,更重要的是,这个社会会越来越弱;实际上,即使在早期,女的每一次脱掉裤子都认为能 从你身上抠出更多的回报,而你每一次脱掉裤子都认为在未来她不能得逞,否则你早跑了。这就像买卖股票,每一个时刻都有掌握着相同资金的人认为这支股票未来 会涨或跌。可以说,你们在“双赢”,以越来越大的双输概率做代价。
  2:如果你选择了对抗这些本质,好像壮士断腕,在短期内就你个人而言得不到任何好处,女的不会青睐你,而你也明白她们本质成这样是钻你播种本质的空子,而且即使你成功的改造了她们也不会仅仅恩泽你一人。
   所以小弟真的赞叹古人治理社会的结果。男女本性的关系是如此的难以被大众理解,但是古人就有办法让大众按照圣人们的指示去做。我们至少在近期内失去了这 样的能力。从统计角度来看,在现在的人群中依靠荣誉激励愿意牺牲自己的利益来选择第2种方式的已经不占多数了,所以烦请兄弟们帮忙多多讨论,既然谎言重复 100遍在大众中就变成了真理,那么把我们认为对的事情说100遍也许也能改变些舆论环境。改变舆论环境,这是目前所能看到的唯一希望。
  
  自私,还是更自私,兄弟们,这是个问题。
  
  “世上很难得有完美的观点,你若不赞同一个观点,最好的方式就是说出你的观点然后来比较。政府除外,因为政府收了税。”
  好的观点:
  1。基于逻辑而不是感觉;
  2。能解释过去现在的事实,从比例上而不是举例上;
  3。能更准确的预测未来。

Finished: Zhejiang Univ. 2007 ACM Local Contest

It is the first time and the last time I engaged in the Zhejiang Univ. ACM contest.
Although our team Eagle had confidence that we would accomplish the goal: get better rank than preliminary contest, we finally resoved just only one question. Sigh~
However, this experience with my two team members: boss and spinach is very exciting and curious. Hope for next collaboration with them within projects of another topics^_^

On the other hand, I have more interests in ACM contest. It is really competitive for every student major in computer science or other related subjects. What is more important for myself is that I get happiness from acm contest. It is the essence!

2007年4月4日星期三

TopCoder任命吴嘉之为中国技术副总裁

新浪科技讯 4月3日消息,TopCoder宣布任命吴嘉之为中国技术部门副总裁。TopCoder是一
家全球性的在线编程竞赛、技能评估,以及竞赛软件开发公司。

  之前,该公司在中国以雇用北师大天才女生吴莹莹,担任亚洲区副总裁而在国内引起
轩然大波。据吴莹莹透露,今天吴嘉之已经正式上任,开始了新的工作。目前该消息已经
得到吴嘉之本人证实。

  据悉,吴嘉之以用户名“WishingBone”,闻名整个TopCoder。今后,他将负责监管针
对所有竞赛和技术的系统及应用程序的开发,并将负责在中国为 TopCoder 软件程序引进
和培训新员工。

  吴嘉之曾就读于浙江大学计算机科学与技术学院和竺可桢学院。他曾经获得TopCoder
以及美国计算机协会 (ACM) 国际大学生程序设计竞赛 (ICPC) 往届冠军。

  TopCoder公司公开的文档显示,吴嘉之于2002年5月年进入 TopCoder。在随后两年半
的时间里,他在45项组件竞赛中创记录地赢得了39项。他还曾担任过 TopCoder 的300多个
组件项目的架构师、汇编程序员、评审委员会成员以及 TopCoder 和 ACM/ICPC 亚洲地区
主评审员。2004年12月,吴嘉之成为 TopCoder 的汇编合同工 (assembly contractor),
他在该职位一直工作到现在被任命的职位。(刘阳)

  吴嘉之的官方履历:

  -- TopCoder Collegiate Challenge(TopCoder 大学挑战赛),国际比赛地区冠军,2
003年;

  -- ACM 国际大学生程序设计竞赛 (ACM/ICPC),2003年,冠军,会津;2003年,亚军
,西安;2002年,第4名,北京;2003年,全球总决赛第13名。

  -- 国际大学生数学建模竞赛 (International Collegiate Mathematical Contest i
n Modeling),二等奖,2002年;

  -- ZJU Google Camp 创立者兼2006年第一任会长。于同年担任谷歌(Google) 的技术
实习生;

  -- 为浙江大学的 ACM/ICPC 团队指导并创建了新的培训课程,使其在2005年的全球总
决赛中取得成功;

  -- 在 TopCoder 的履历和名誉-- 有史以来最多产而最成功的员工之一。