C++不垃圾,只是Java很傲慢
《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很傲慢相关推荐
- 学习java很痛苦_Java日期细微的痛苦提醒
学习java很痛苦 这些天我不再需要使用java.util.Date了,但是最近选择这样做,这让我想起了使用与Java Date关联的API的痛苦 . 在这篇文章中,我看了弃用的参数化Date构造函数 ...
- Java很傻,但是IDE很聪明,Intellij IDEA 是一款好产品
投递人 itwriter发布于 2013-06-06 13:34评论(6)有532人阅读原文链接[收藏]«» @李先 Loki 来自伯乐在线 对于编程语言来说,什么是生产力?我觉得,更高的抽象层次就是 ...
- 没学历学java很难找工作吗
说实话不是学Java很难找工作,是以后找工作基本都会看学历,学历这个东西说重要也重要,因为它决定了你的简历能不能呈现到面试官面前,如果你的学历不够的话很有可能在第一轮简历就被刷下去了,它根本就不会呈现 ...
- ppt怎么让人耳目一新_哦,您认为Java很烂吗? 多么令人耳目一新
ppt怎么让人耳目一新 还在谈论销售会议中的信贷紧缩吗? 对猪流感感到惊慌? 那那个怪异的Lady Gaga怎么样-她接下来会做什么? 所有这些都是2009年Twitter的主要趋势.2009年也&q ...
- java 很垃圾_JAVA吧真的很垃圾!!!
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 作为硬件编辑,经常去看一些IT类的网站,时间长了,就发现一个奇怪的事情,在几乎所有的产品新闻或是产品评测后面,几乎都有人写着这样的读者评论--" ...
- java内存分配和垃圾回收,Java内存分配与垃圾回收
1.JVM管理的内存包含下图所示的几个运行时数据区域,其中方法区和堆为线程共享的数据区域,程序计数器,虚拟机栈以及本地方法栈为线程私有的数据区域. 程序计数器:可以看做是当前线程所执行的字节码的行号指 ...
- 垃圾回收 | Java垃圾回收,这杯咖啡,不仅好喝,而且实用!
Hi! 我是小小,今天是本周的第六篇,本篇将会着重的讲解关于Java垃圾回收机制. 垃圾回收的意义 Java语言的显著特点就是引入了垃圾回收机制,使得C++程序猿最为头疼的内存管理问题就直接解决掉了. ...
- acm竞赛java很少_ACM比赛中JAVA的应用
Chapter I. Java的优缺点各种书上都有,这里只说说用Java做ACM-ICPC的特点: (1) 最明显的好处是,学会Java,可以参加Java Challenge (2) 对于熟悉C/C+ ...
- Java很难找工作了?
大家好. 最近有不少同学在微信上问我春招什么时候开始.鹅厂开始春招了么等等. 这里统一说一下吧,根据去年的时间线,大厂一般在二月末或者三月初陆续开启春招. 也就是说现在基本上已经开始了,这个时间想要全 ...
- 垃圾回收(GC) 很干,很全
说一下垃圾回收机制 垃圾回收主要针对的是JVM的堆内存,我讲一下我了解的hotspot实现的jvm, 分为新生代和老年代,按照以前的说法,还有一个永久代,永久代在方法区里(物理上跟老年代相连),保存了 ...
最新文章
- 计算机自动连续工作的基础是存储程序原理,计算机的存储程序工作原理是什么...
- OpenCV之imgproc 模块. 图像处理(1)图像平滑处理 腐蚀与膨胀(Eroding and Dilating) 更多形态学变换 图像金字塔 基本的阈值操作
- 目标、物体识别(检测)object detection 中的 bounding boxes 是什么? 边界区域、边界框、边界盒
- python array_python数组array.array(转帖)
- php使用imagemagick,PHP的ImageMagick使用;
- 前端学习(2812):前端小程序学习之小程序发展历史
- java禁止修改map_Java中实现不可变Map
- Date 类的总结。含代码。
- wait 和 sleep 区别
- jQuery MVC 科室异步联动
- Iphone 5s 8.0.2越狱
- 自动售检票系统是基于计算机,车站自动售检票系统存在的必要性
- 德·摩根定律的验证(De Morgan’s Laws)
- java两两组合(不重复)
- 2019河南省第十二届ACM大学生程序设计竞赛参赛感
- 单因素方差分析(ANOVA)及其Python库
- android环境监测,基于Wi―Fi和Android家居环境监测与实现
- opencv利用投影法进行水平切割和垂直切割
- 【Mac 教程系列第 9 篇】如何把 Mac 中的程序坞移动到另一个屏幕
- 【论文简述】Multiview Stereo with Cascaded Epipolar RAFT(ECCV 2022)
热门文章
- React开发中常见问题和 Warning
- Java命令运行没反应_cmd中执行java命令没有输出结果
- python爬取图片失败什么原因_请问下面这个python3.5下的爬虫程序有什么错误,为什么运行正常 但是不爬取图片?...
- mac mysql read only_mac Read-Only filesystem
- 入门highchart 第一天—— 环形图
- C# 异步函数同时执行后再执行其它函数async
- Shell 脚本执行错误 $‘\r‘:command not found
- Yii Framework2.0开发教程(6)数据库mysql--ActiveRecord
- java获取jsp页面下拉列表框_jQuery+jsp下拉框联动获取本地数据的方法(附源码)
- LINUX SHELL脚本如何判断一个目录下有没有文件