《Thinking in C++》及《Thinking in Java》的作者Bruce Eckel向来是个“拥C++反Java”派,他曾经不止一次的提到,C++语言特性的添加有多么的深思熟虑,而Java又是如何的把一些奇怪的东西不停的加进去。Bruce认为,理解语言特性为什么会存在是非常有帮助的。他将其称之为“语言考古学”。

在C++委员会会议上我所能找到的,是C++社区里最聪明的一群人,群英荟萃,为我答疑解惑。我很快意识到,这种方式之好,远超我在任何一门研究生课程中之所得。如果考虑到研究生的机会成本,这还是一笔在财务上要划算得多的生意。

我被深深吸引住了,坚持出席了有大约8年的时间。在我走后,委员会仍继续前行;虽标准仍未制定完成,但彼时Java已经出现了,还有一些其他(语言)的草案也问世了(这是技术刺激成瘾者的毛病——我的确钻研某一门语言,但我也一直在寻找更有生产力的手段:那些前景看起来很光明的语言特性可以毫不费力地分散我的注意力)。

每次大家见面的时候,我都会抛出一列清单,这是我累积下来的有关C++的棘手问题列表。通常我会请他们在几日内予以澄清。出席委员会能看到的最有价值的东西就是这个,当然,还包括得以早早接触到即将公布的新特性。

从长远来看,把语言特性添加进C++的谜团里面并观察它,是一门深奥的学问。现在说三道四是一件很简单的事情,说什么C++太烂了,设计太糟糕了等等。在对C++设计时所受的约束都没有任何理解时,很多人就这样脱口而出了。Stroustrup(51CTO编者注:这个Stroustrup也就是邀请作者参会的Stroustrup,也就是C++语言的设计师Stroustrup)的约束是,C程序应该稍作改动,或者最好不做改动,就能在C++下编译。且不管这是不是完全合乎逻辑,但它给C程序员提供了一个很好的演进路径。不过这存在较大的局限性,需要把每一项大家抱怨不已的困难特性都一一虚拟化。由于这些特性难以理解,许多人就直接得出结论说C++设计糟糕,而这远非事实。

在语言设计上,Java用傲慢的态度对待这一认识。关于这一点,我在《Java编程思想》及许多博文上都写过了。因此我的长期追随者都知道,由于Gosling(Java语言之父)和Java语言设计者对C++的否定态度,Java一开始就把我拧到了错误的方向。说实话,我与Gosling 的首次“邂逅”印象糟糕——那是很多年以前的事了,当时我刚进入第一家公司,第一次开始使用UNIX (Fluke,生产电子测试设备;我在里面做嵌入式系统编程)。有一位软件工程师辅导我,教我使用emacs。不过当时公司里唯一的工具只有Gosling Emacs的商用版(Unipress)。如果你做错了什么,程序会侮辱你,把你叫做火鸡,并把屏幕填满垃圾。这样的东西出现在了一个商用产品上,而我们公司可是花了相当一笔钱的。不消说,等到Gnu emacs变得稳定起来后,公司马上就换到了Gnu emacs上(我见过Richard Stallman。当然,他是个疯狂的家伙。不过他也是绝顶聪明的:他知道当遇到麻烦的时候,你需要的是帮助,而不是侮辱)。(51CTO编者注:Richard Stallman即Gnu emacs的开发人员,美国一位著名黑客。

我不知道对Gosling印象的这段形成经历在多大程度上影响了我后面对他工作的看法,但事实上,“我们看见它太差劲了,就决定拿出自己的语言”,对C++的这种态度于事无补。尤其是当我开始在《Java编程思想》的写作过程中把它弄清楚,并屡次发现,那些草率决定的语言特性与库,都不得不予以修订——确实如此,其中的大部分都必须要修订,有些修订还是在程序员已经忍受了多年之后才落实。在许多场合下,Gosling坦诚他们必须快马加鞭,否则就要被互联网革命超越了。

我发现,理解语言特性为什么会存在是非常有帮助的。如果是由大学教授一下子和盘托出,把它们端到你面前,你势必就会构想出这门语言的一个神话,说“这种语言特性之所以存在,肯定有一些真正重要的原因,这些原因只有创建这门语言的聪明人才能理解,我是理解不了的,我信赖它就是了”。从某方面来说,对语言特性这种基于信仰的接受是一种负担;它阻止你对所发生的事情进行分析和理解。在我的主旨演讲中(Bruce将在未来几天参与一个主旨演讲),我会关注一些特性,并检查一下它们在不同语言中是如何被实现的,以及为什么被实现。

这里就有个例子。对象创建。在C语言中,声明了变量之后编译器就会为你创建堆栈空间(未经初始化,除非你初始化,否则会有垃圾数据)。但是如果你想要动态地做这件事情,你就得使用 malloc() 和 free()这两个标准库函数,还要小心翼翼地手工执行完所有的初始化及清理工作。如果你忘了,就会出现内存泄漏等类似灾难,这是常有的事。

有关动态对象创建:一般来说,编译器将内存分为三部分:静态存储区域、栈、堆。静态存储区主要保存全局变量和静态变量,栈存储调用函数相关的变量、地址等,堆存储动态生成的变量,在c中是指由malloc,free运算产生释放的存储空间,在c++中就是指new和delete运算符作用的存储区域。

因为malloc() 和 free() “仅仅”是库函数,在基本编程课上,应有的相关知识通常没有被传授,令人既疑惑不解又胆颤心惊。当程序员需要分配大量的内存空间时,他们就不去学如何来使用这些函数进行处理,取而代之的是常常就分配一个巨型数组的全局变量了事(不是开玩笑),数组之大,远远超过他们曾自认为所需的空间。程序似乎工作了,再说了,好像谁都不会用到产生越界——因此,当多年之后它的确发生的时候,程序中断了,而某个可怜的家伙就得一头钻进去,把错误在哪里这个谜底给找出来。

Stroustrup认为动态分配需要更简单、更安全——这一块得放到语言核心中,而不是降格为库函数。还必须要与初始化和清理一起协同工作,初始化和清理必须由构造函数和析构函数分别提供,以便为所有对象提供相同的保证。

这个问题是影响了全部C++决策的一块里程碑:对C的向后兼容性。理想情况下,对象的堆栈(heap)分配可只需忽略即可。但C的兼容性要求进行堆栈(stack)分配,因此必须对heap对象和stack对象进行区分。为了解决这个问题,C++从SmallTalk挪用了new 这个关键字。创建 stack 对象只需声明即可,像这样: Cat x;或者带参数的情况下, Cat x("mittens");。而创建heap 对象时,就使用new,像这样: new Cat x; 或者 new Cat x("mittens");。利用这个约束,我们得到一个优雅而一致的解决方案。

自从判定C++的一切都做得不好且过于复杂之后,Java就产生了。具有讽刺意味的是,Java 决定把 stack 彻底抛弃了(特别是忽略了基本类型上的失败,这点我已经在别的地方指出过了)。真好啊,既然所有对象都是在heap上分配的,区分stack和heap的分配就没有必要了。他们可以轻易说 Cat x = Cat() 或者 Cat x = Cat("mittens")。或者甚至更好地,用联合的类型引用来消除重复(不过那样——还有像闭包(closure)之类的其他特性——就显得“太长”了。因此我们反而离不开Java的平凡版;类型推导已经讨论过了,但我敢打赌那不会发生,也不该发生。因为这会在给Java增加特性的同时带来问题)。

Guido Van Rossum (Python的创建者)采用了一个最小化的方案——经常为人所痛斥的空白的使用,正说明了他对语言简洁性的追求。既然 new 关键字不再必要,他就省去了,好像这样: x = Cat("mittens")。Ruby 也可能用了这种方法,不过Ruby其中一个主要的约束是尽可能追随Smalltalk,因此在Ruby是这样的:x = Cat.new("mittens") 。但Java以贬低C++做事的方式为准则,以至于用了new 这个关键字成了一个迷了。自研究了该语言在其他地方所做的决策后,我的猜测是,他们是不是从来就没有意识到,这东西根本就是可有可无的?

因此这就是我所说的语言考古学的意思。我希望人们能用一个更好的视角来看待语言设计,并在学习一门编程语言时,能有更多的批判性思维过程。

转载于:https://my.oschina.net/alphajay/blog/3859

C++不垃圾,只是Java很傲慢相关推荐

  1. 学习java很痛苦_Java日期细微的痛苦提醒

    学习java很痛苦 这些天我不再需要使用java.util.Date了,但是最近选择这样做,这让我想起了使用与Java Date关联的API的痛苦 . 在这篇文章中,我看了弃用的参数化Date构造函数 ...

  2. Java很傻,但是IDE很聪明,Intellij IDEA 是一款好产品

    投递人 itwriter发布于 2013-06-06 13:34评论(6)有532人阅读原文链接[收藏]«» @李先 Loki 来自伯乐在线 对于编程语言来说,什么是生产力?我觉得,更高的抽象层次就是 ...

  3. 没学历学java很难找工作吗

    说实话不是学Java很难找工作,是以后找工作基本都会看学历,学历这个东西说重要也重要,因为它决定了你的简历能不能呈现到面试官面前,如果你的学历不够的话很有可能在第一轮简历就被刷下去了,它根本就不会呈现 ...

  4. ppt怎么让人耳目一新_哦,您认为Java很烂吗? 多么令人耳目一新

    ppt怎么让人耳目一新 还在谈论销售会议中的信贷紧缩吗? 对猪流感感到惊慌? 那那个怪异的Lady Gaga怎么样-她接下来会做什么? 所有这些都是2009年Twitter的主要趋势.2009年也&q ...

  5. java 很垃圾_JAVA吧真的很垃圾!!!

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 作为硬件编辑,经常去看一些IT类的网站,时间长了,就发现一个奇怪的事情,在几乎所有的产品新闻或是产品评测后面,几乎都有人写着这样的读者评论--" ...

  6. java内存分配和垃圾回收,Java内存分配与垃圾回收

    1.JVM管理的内存包含下图所示的几个运行时数据区域,其中方法区和堆为线程共享的数据区域,程序计数器,虚拟机栈以及本地方法栈为线程私有的数据区域. 程序计数器:可以看做是当前线程所执行的字节码的行号指 ...

  7. 垃圾回收 | Java垃圾回收,这杯咖啡,不仅好喝,而且实用!

    Hi! 我是小小,今天是本周的第六篇,本篇将会着重的讲解关于Java垃圾回收机制. 垃圾回收的意义 Java语言的显著特点就是引入了垃圾回收机制,使得C++程序猿最为头疼的内存管理问题就直接解决掉了. ...

  8. acm竞赛java很少_ACM比赛中JAVA的应用

    Chapter I. Java的优缺点各种书上都有,这里只说说用Java做ACM-ICPC的特点: (1) 最明显的好处是,学会Java,可以参加Java Challenge (2) 对于熟悉C/C+ ...

  9. Java很难找工作了?

    大家好. 最近有不少同学在微信上问我春招什么时候开始.鹅厂开始春招了么等等. 这里统一说一下吧,根据去年的时间线,大厂一般在二月末或者三月初陆续开启春招. 也就是说现在基本上已经开始了,这个时间想要全 ...

  10. 垃圾回收(GC) 很干,很全

    说一下垃圾回收机制 垃圾回收主要针对的是JVM的堆内存,我讲一下我了解的hotspot实现的jvm, 分为新生代和老年代,按照以前的说法,还有一个永久代,永久代在方法区里(物理上跟老年代相连),保存了 ...

最新文章

  1. 计算机自动连续工作的基础是存储程序原理,计算机的存储程序工作原理是什么...
  2. OpenCV之imgproc 模块. 图像处理(1)图像平滑处理 腐蚀与膨胀(Eroding and Dilating) 更多形态学变换 图像金字塔 基本的阈值操作
  3. 目标、物体识别(检测)object detection 中的 bounding boxes 是什么? 边界区域、边界框、边界盒
  4. python array_python数组array.array(转帖)
  5. php使用imagemagick,PHP的ImageMagick使用;
  6. 前端学习(2812):前端小程序学习之小程序发展历史
  7. java禁止修改map_Java中实现不可变Map
  8. Date 类的总结。含代码。
  9. wait 和 sleep 区别
  10. jQuery MVC 科室异步联动
  11. Iphone 5s 8.0.2越狱
  12. 自动售检票系统是基于计算机,车站自动售检票系统存在的必要性
  13. 德·摩根定律的验证(De Morgan’s Laws)
  14. java两两组合(不重复)
  15. 2019河南省第十二届ACM大学生程序设计竞赛参赛感
  16. 单因素方差分析(ANOVA)及其Python库
  17. android环境监测,基于Wi―Fi和Android家居环境监测与实现
  18. opencv利用投影法进行水平切割和垂直切割
  19. 【Mac 教程系列第 9 篇】如何把 Mac 中的程序坞移动到另一个屏幕
  20. 【论文简述】Multiview Stereo with Cascaded Epipolar RAFT(ECCV 2022)

热门文章

  1. React开发中常见问题和 Warning
  2. Java命令运行没反应_cmd中执行java命令没有输出结果
  3. python爬取图片失败什么原因_请问下面这个python3.5下的爬虫程序有什么错误,为什么运行正常 但是不爬取图片?...
  4. mac mysql read only_mac Read-Only filesystem
  5. 入门highchart 第一天—— 环形图
  6. C# 异步函数同时执行后再执行其它函数async
  7. Shell 脚本执行错误 $‘\r‘:command not found
  8. Yii Framework2.0开发教程(6)数据库mysql--ActiveRecord
  9. java获取jsp页面下拉列表框_jQuery+jsp下拉框联动获取本地数据的方法(附源码)
  10. LINUX SHELL脚本如何判断一个目录下有没有文件