冒号课堂§6.1:系统语言

冒号课堂

第六课 语言简评(1)


课前导读

本课对一些主流语言进行了简单的比较和评价。一家之言,权作助兴。

本课共分四节——

  1. 系统语言——权力的双刃剑
  2. 平台语言——先搭台后唱戏
  3. 前台语言——视觉与交互的艺术
  4. 后台脚本——敏捷开发的利器

6.1系统语言——权力的双刃剑

居高者形逸而神劳,处下者形劳而神逸                        —《洪应明·菜根谭》

 

关键词:C族语言,C语言,C++,D语言

摘要:简谈CC++D

 

  预览

 

·          通禅悟道者拈花不语,坐井观天者蛙鸣鼓噪

·          Java程序员大多被惯坏了,环保意识要淡薄得多

·          (指针)用得好可以是削铁如泥的神兵利器,用得不好则可能是自我毁灭的罪恶渊薮

·          OOP又不是金子,含量越高越好。试图把一切都装进OOP的箱子里的想法无异于削足适履

·          它们(系统语言)的理念是:优化机器的时间而不是人的时间,优化机器的记忆而不是人的记忆;假设编译器是愚蠢的而程序员是聪明的,因此赋予程序员更多的权利、义务与责任

·          C++是匹无辔无鞍的野马,看似桀骜不驯,若能顺性而御,必能足踏飞燕,行千里而不劳


  提问 


  • 为什么C++不支持自动垃圾回收?
  • C++中如何解决内存释放问题?
  • 系统语言有哪些特点?
  • 在不引入OOP的前提下,C语言可以借鉴C++的哪些特征?
  • D语言比C++有哪些改进?
  • 在电脑性能日益提升的今天,还有必要在乎程序的性能和效率吗?


    讲解

 

教室里,学员们正热火朝天地讨论着流行的编程语言。冒号推门而入,仿佛沸水锅里被浇了一瓢冷水,立刻平静下来。

冒号笑吟吟地看着大家:“怎么不讨论了?”

众人齐道:“该您了!”

“首先需要声明的是,本课评论编程语言,乃是应众位之邀,实非本意。”冒号变得严肃起来,“因为这种评论,不可避免地会带上个人色彩,容易产生误导。有道是,通禅悟道者拈花不语,坐井观天者蛙鸣鼓噪。

众人迅速自动对号:看来我们就是一群蛤蟆。

“这样一来,我的处境就很尴尬了。”冒号自嘲着。

有人在幸灾乐祸地偷笑。

“也罢,即使作蛙鸣,至少也要先跳出井来。”冒号毅然决然地加入了蛤蟆的行列,“要谈,就旗帜鲜明地谈,该赞叹的就赞叹,该鄙视的就鄙视。说些你好我好大家好之类不痛不痒的话,倒不如不说。”

叹号一拍大腿:“好,这样才够痛快!”

问号忍不住问:“您究竟打算比较哪些主流语言呢?”

冒号回答:“就谈谈第一堂课提到的最流行的十二种语言吧。按语法特征可将它们分为三类:C族静态语言五种——CC++JavaC#D;非C族静态语言两种——VBDelphi;动态语言五种——PerlPHPPythonRuby JavaScript 。”

叹号表示怀疑:“这么多种语言怎么比较得过来?”

冒号解释:“我们主要比较第一类的C族语言,这些也是今后学习的重点,其他的只是泛泛而谈。”

引号猜测:“因为他们更重要?”

“可以这么说。”冒号直截了当,“毋庸讳言,在当今的主流语言中,C族语言应用范围之广、使用人数之多、影响力之巨都是其他类语言所无法比拟的。它们之间的关系从名字上就能看出:C语言的前身是B语言;其后是C++Java曾被称为C++++--,意思是在C++上增点东西再减点东西;C##就是四个叠起的加号[1];最后D语言干脆在字母上进行升级。”

句号推断:“B语言、C语言、D语言,下一个该D++D#E语言了。”

谁知冒号却说:“E语言已经有了,与Java的语法很像。甚至F语言也有了,但不是C族语言,而是Fortran族的。这不,微软还在.Net平台上推出了F#语言,不过这里的F指的是‘Functional’,即函数式。”

逗号向往着:“不如直接搞个终极的Z语言,成为全世界程序员的唯一指定语言,多省事!”

“这难度不亚于全人类共用一种语言。”冒号笑道,“愿望是美好的,我们还得面对现实。不扯远了,你们先谈谈一下这些C族语言各自的特点吧。”

众人心想:老冒怎么跟国足一个毛病,老喜欢回传,就是不直接射门,真是急煞人也!

问号拣了个软柿子:“C语言是C族老大,又是唯一的纯过程式语言,当然与众不同啦。”

引号一板一眼:“C++在过程式的基础上又引入对象式和泛型式,同时保持了C的高效性和底层开发能力。”

逗号接道:“Java既继承了C++的优点,又克服了C++的复杂性,虽然底层开发能力有所减弱,但具备平台无关性。”

句号不紧不慢:“C#兼具C++Java各自的优点,但效率上不如C++,跨平台方面不如Java。”

叹号后悔嘴慢:“剩下一个最陌生的D语言,在第一堂课之前还真没听说过,怎么挤上主流语言位置的?我想。。。呃,它总该比C++要高级吧。”

冒号评价:“各位谈得虽然简单了些,也算八九不离十吧。下面我稍微展开些来讲。”

此时众人有一个共同的愿望,希望老冒这次能痛快地单刀赴会、直捣黄龙。

冒号似乎看出大家的心思,开始口若悬河:“关于C语言,前面多次提到。这是一把历久弥新的宝剑,一旦出鞘,依旧寒光逼人,锋利无俦。有了它,便如战将有了佩剑,平添一分独闯敌营的胆气。尽管以现代的眼光来看,它存在不少缺点,但即使抛开C语言辉煌的历史不谈,单就其以如此高龄在诸多后辈冲击之下仍屹立不倒而论,让人无法对其多加苛求。”

逗号提出异议:“但语言不是让人崇拜的,而是让人运用的。一门语言无论过去如何荣光,如果不适应现代发展趋势,还是可能被淘汰。”

“说得非常好!”冒号竟然鼓起掌来,“迄今为止本课堂对于具体知识的讲授不算太多,但一直提倡独立思考,不要盲从权威。如果你们能做到这一点,本班的目标也就实现了一半。回头再说说C语言,它源自Unix操作系统的开发,以其良好的抽象性和可移植性取代了汇编语言作为系统开发语言。因其简洁实用、灵活高效,很快从系统领域发展到其他领域而成为通用语言。随着新兴语言的崛起以及硬件性能的大幅提高,C语言的缺点也日益显著:过于宽松的类型检查、容易出错的内存管理、相对贫乏的语言特征等等。虽然自身还在发展,它的市场份额日益减少乃是不争的事实。但在相当长的时间内,它在其所擅长的领域里仍会占举足轻重的一席之地。如果C能借鉴C++ 命名空间、重载、异常处理和STL等非OOP的特征,它的生命力绝不会比任何OOP语言弱。附带说一句,C虽然没有直接支持OOP的语法,但经过适当的设计还是能实现OOP[2]。”

引号咨询道:“关于C语言的学习,您有何建议?”

“精读K&R的《The C Programming Language》,此书不过二百页,堪称C语言的剑诀。其中的RDennis Ritchie,是C的创造者,同时也是Unix的缔造者之一,是真正的大师。如今的大师,同博士、教授、院士等头衔一样,严重地通货膨胀了。”冒号不无感慨。

问号尖锐地问:“C++既保持了C的底层开发能力,又引入了OOPC的处境想必更加艰难吧?”

冒号坦承:“这是不假。C++成功的一个重要因素是对C语言的兼容,由此吸引了大批的C程序员。但这不是没有代价的,C++在兼容C的同时也保留了C的许多缺陷。Java成功的地方有很多,一个不容忽视的因素是它彻底摆脱了与C兼容的桎梏。由于C++C的改革不彻底,又过于庞杂,并且效率上不如C,这使得C仍有其生存空间。略有讽刺意味的是,对C++批判最激烈的往往来自C的社区,比如Linux之父Linus Torvalds就曾激烈地批判过C++。”

Linus?那可是我的偶像呢!”叹号惊讶道。

冒号劝诫:“如果你因为是他的粉丝而后悔学C++,那就是为他人的偏执买单,不管那人名气有多大。”

句号指出:“C++最为人诟病的地方有:语法过于复杂,学习曲线陡、开发效率低;支持的范式过多;OOP不彻底;自省(reflection)功能不足;支持指针操作导致安全隐患;没有自动垃圾回收,容易内存泄漏;没有线程支持;没有丰富的标准库支持图形界面、网络编程等。”

“罪状不少哇!这些说法都有一定道理,但有些也有失公允。且听我一一道来。”冒号当起了辩护律师,“C++比较复杂这点没错,Stroustrup说过一句耐人寻味的话: 一种语言不够复杂是因为它还不够成熟。成人肯定比儿童复杂,因为他要承担更大的责任。大家不妨看看Java1.0到即将的7.0C#1.0到即将的4.0的发展过程,是否应证了这一点?当然C++的复杂度的确高于其他语言,但如果不执着于奇技淫巧,它绝非高不可攀。C++的开发效率相比JavaC#,差距主要在两个方面:一是标准库不够完善,二是需要手工回收垃圾。关于前者,的确是C++的一大软肋,标准库竟然连企业应用中最常用的图形界面、网络编程、数据库处理、多线程等都不能涵盖,严重障碍了生产力。其实C++也有苦衷,不像JavaC#那样有大公司的鼎力支持,只靠效率极为低下的标准委员会来维护。98年的一个标准直到03年还在修订,下一个标准至少要到09年。连Stroustrup都在哭穷,声称没有足够的人力和时间来开发标准库,可为何广受赞誉的Boost库至今仍徘徊在标准门外?考虑到Boost的创办人大多出自标准委员会,其他无此背景的类库恐怕更难登C++之大堂了。相比之下D语言更惨,虽然天生丽质,苦无豪门青睐,只好一直待字闺中。”

叹号感慨:“金钱才是技术的最大推动力啊!”

“话糙理不糙。”冒号也很无奈,“再来谈谈有关自动垃圾回收的问题。在C++中,程序员也不是非得手工清理垃圾不可的。更好的办法是遵循RAII的惯用法(idiom[3],通过智能指针smart pointer)来解决内存释放问题。”

逗号听不明白:“什么是RAII?”

RAIIResource Acquisition Is Initialization的缩写,直译为‘资源获取即初始化’。”冒号解释,“其实更准确的叫法应该是RRIFResource Release Is Finalization),即‘资源释放即终结化’[4]。其思想是:将资源的取放与某一对象的生命周期绑定,初始化对象时获取资源,终结化对象时释放资源。用户代码不再直接管理资源,只需控制相应的对象即可。这样代码得以简化,资源的有效性也得以保障,并且还是异常安全的exception-safe[5]。”

问号猜想:“在Java中没有这种用法,是因为它已经有了垃圾回收器吗?”

冒号摇摇头:“问题的关键不在这里。资源不只限于内存,还包括文件、线程锁、数据库连接等等,这些都不是垃圾回收器所能解决的。看看Java的数据库应用代码吧,对于那些频繁出现的被try/catch/finally包裹的resultset.close()statement.close()connection.close(),你是习以为常呢,还是不胜其烦?”

逗号眼睛一亮:“如果采用RAII的技巧,这些都可以省去了吗?”

冒号再次摇头:“可惜Java不像C++D那样,能在stack)上创建对象。栈对象有一个的特点,一旦超出其作用范围,便自动释放内存。在此之前会调用析构函数destructor),后者继而调用释放资源的代码。”

几声叹息清晰可闻。

冒号续道:“另一方面,尽管自动垃圾回收机制逐渐为大众所接受——据说C++0x也将部分地支持它——但这种机制也存在缺陷。比如一个Java程序如果在某一时段极耗内存,由于自动垃圾回收的不定时性,不能保证及时清理内存,可能会抛出OutOfMemoryError的错误。对于内存有限的系统或实时系统来说,这绝对是一个致命的软肋。C++不支持自动垃圾回收,正是基于这些方面的考虑。Stroustrup非常顾虑自动垃圾回收带来的时间和空间上的过多开销,并且担心它会影响C++完成其所肩负的底层任务。另外,千万不要以为有了自动垃圾回收机制就一劳永逸、万事大吉了。Java程序一样会有内存泄漏,其几率甚至可能比C++的更大,因为C++程序员对此更有戒心,而Java程序员大多被惯坏了,环保意识要淡薄得多。”

问号直奔要害:“您如何看待CC++中的指针?”

冒号欣然接招:“指针是CC++最大的特色,其他语言要么不支持,要么支持得有限。CC++可以说是成也指针,败也指针。用得好可以是削铁如泥的神兵利器,用得不好则可能是自我毁灭的罪恶渊薮。但由于二者定位于系统语言,而指针对于底层操作是必不可少的。同样道理,二者的数据类型的转换比其他静态类型语言更自由,也是源出于此。”

句号总结:“能力越大,责任越大,风险越大。

“正是此意!”冒号重重地敲了一下桌子,“此话既适用于编程语言,也适用于程序员。至于C++缺少对自省功能的支持,也是因为追求效率,不愿在元数据上花时间和空间。说到C++支持的范式过多,程序员过于自由,代码不标准难维护,这就如同埋怨餐馆提供的菜式过多以致难以摆出一桌酒席一样可笑。最后,指责C++不是100OOP的说法更是荒谬之极。OOP又不是金子,含量越高越好。试图把一切都装进OOP的箱子里的想法无异于削足适履。典型的如Java中的Math类,逻辑上压根儿就不存在什么Math对象,清一色的static方法和常量就是最好的讽刺。在C++中只要在mathnamespace中定义一些自由函数就可以了,自然而简洁。作为一个佐证,JavaJ2SE5.0引进了静态导入(static import)机制[6],不仅在形式上简化了调用代码,也在思维上容忍了非OOP的过程式。”

引号发觉:“您好像把对C++所有的责难都化解了。”

“可恨之人必有可怜之处嘛。”冒号俗语反用,“其实C++仍有不少亟待改进之处,D语言就是很好的启示。D语言的提供了可控制的垃圾回收器;支持线程同步;支持动态数组dynamic array);支持嵌套函数nested function);支持契约式设计design by contract);废除了CC++ 中令人头痛的头文件header file)等等。这些都是C++程序员梦寐以求的特征。”

逗号很奇怪:“为什么D语言名气这么小?”

句号吟道:“千里马常有,而伯乐不常有,大腕伯乐更稀有。”

众乐。

冒号拔高了调门:“既然系统语言主要为底层系统的开发服务,这就决定了它们的理念是:优化机器的时间而不是人的时间优化机器的记忆而不是人的记忆;假设编译器是愚蠢的而程序员是聪明的,因此赋予程序员更多的权利、义务与责任无视这种背景和理念而去与其他语言相较,完全是不着筋节,不值一哂。当然这并不排斥系统语言用于应用开发,尤其是C++D语言。需要强调的是,常见的‘C/C++’的说法很不科学。CC++虽有千丝万缕的联系,但一个简单,一个复杂;一个纯过程式,一个集过程式、对象式、泛型式和元编程于一体。貌合神离,不宜混为一谈。”

叹号一个问题憋了半天,不吐不快:“我有一个问题:如今电脑性能这么高,CC++如此强调程序的性能和效率还有必要吗?”

“绝对有必要!”冒号斩钉截铁,“其一、纵向看,用户的耐心与电脑的性能成反比,早年一个386人们就满足了,如今却忍受不了586;以前16M内存就不错了,现在1G都嫌小。其二、横向比,占用资源过多、运行相对缓慢的软件竞争力也低。其三、在一些应用领域如人工智能、大型计算等方面,普通电脑的性能还远远不能满足要求,超级计算机的存在就是明证。其四、仍有些程序跑在资源有限的主机上,比如嵌入式系统。”

引号再次要求:“能推荐一些C++方面的书吗?”

冒号直言相告:“学好C一本书足矣,学好C++即使推荐十本仍有遗珠之憾。可以说C++是苦了编程者,甜了著书人。开个小书单:初级——《C++ Primer》和《Thinking in C++》;中级——《The C++ Programming Language》和《Effective C++》系列;高级——《The C++ In-Depth》系列。这里还要特别推荐一下《The Design and Evolution of C++》,从中你可以看到 C++的设计和演变的来龙去脉,极具启发性。其他的C++精品书籍还有不少,恕不一一列举了。C++是匹无辔无鞍的野马,看似桀骜不驯,若能顺性而御,必能足踏飞燕,行千里而不劳。”


   插语

[1] 更官方的说法是“#”来自音乐中的高半音符号。

[2] 比如文献【4】设计了一种用C来实现OOP的机制。

[3] RAII是由Bjarne Stroustrup首先提出的,参见文献【2】。

[4] 说它更准确,是因为资源获取的代码不一定需要出现在constructor中,但资源释放的代码一定出现在destructor中。

[5] 指即使发生异常(exception)也不会导致资源泄露。

[6] 比如,在静态导入Math类(import static java.lang.Math.*;)后,代码中可以直接调用sqrtlogmax等数学方法,不再需要“Math.”的前缀了。


   总结

·        C++C语言的兼容是其成功的一个重要因素,但同时也继承了C的一些缺陷。

·        C++设计者没有直接支持自动垃圾回收,是担心它造成过大的时空开销,同时会削弱底层开发能力。

·        除了手工释放内存外,C++提倡运用RAII原则解决包括内存在内的资源管理问题。

·        CC++对指针的全面支持和宽松的类型转换限制,均出于底层系统开发的需要。

·        C可以借鉴C++命名空间、重载、异常处理和STL等非OOP的特征。

·        D语言提供了可控制的垃圾回收器,支持线程同步、动态数组、嵌套函数和契约式设计,并废除了头文件和前置声明(forward declaration)。

·        在程序性能与生产效率之间,系统语言更看重前者,它们在赋予程序员更多的权利的同时,也带给程序员更多的负担。

·        程序的性能和效率永远是重要的。一方面,用户对软件性能的期望越来越高;另一方面,有时硬件性能与软件需求并不匹配:有些应用(如人工智能、大型计算)对程序的性能和效率要求极高,有些系统(如嵌入式系统)的资源十分有限。


 “”参考

[1] Bjarne StroustrupThe Design and Evolution of C++Reading, MAAddison-Wesley1994219-222

[2] Bjarne StroustrupThe C++ Programming LanguageSpecial ed.Reading, MAAddison-Wesley2000364-387

[3] Walter BrightD Programming Languagehttp://www.digitalmars.com/d/

[4] Axel Tobias SchreinerObject-oriented Programming with ANSI-Chttp://www.planetpdf.com/codecuts/pdfs/ooc.pdf

posted on 2009-02-08 22:03 郑晖 阅读(3654) 评论(1)  编辑  收藏 所属分类: 冒号课堂

评论

# re: 冒号课堂§6.1:系统语言[未登录] 2009-02-12 23:39 frank

虽然说的比较详细,但整体立场上是在给C++涂脂抹粉。每一种语言都有自己的应用领域和方面,离开具体应用说任何一种语言好或者不好都是不客观不现实的。c++再强大,也不适合开发分布式企业应用。java再强大,对底层设备访问也只能束手。  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
 

导航

统计

公告

博客搬家:http://blog.zhenghui.org
《冒号课堂》一书于2009年10月上市,详情请见
冒号课堂

留言簿(17)

随笔分类(61)

随笔档案(61)

文章分类(1)

文章档案(1)

最新随笔

积分与排名

最新评论

阅读排行榜

评论排行榜