Linus Torvalds曾经在十多年前尝试用C++来开发Linux内核,由于种种原因,很快失败了。自那时起他就不时表达对C++的不满。
最近,Linux之父Linus Torvalds为了Linux内核开发而专门打造的版本控制软件Git已经引起了业界的广泛关注。昨天,有一位Dmitry Kakurin老兄在查看了源代码之后,发现使用的是纯C而非C++,表示不可理解,他直言:“别拿可移植性说事儿,这是屁话(BS, bullshit)。“(此外,他还批评Git蛮力地直接操作文本,既啰嗦又易错,而且很难跟上高层代码逻辑。)
这个BS引起了Torvalds的强烈反应,他用“*YOU* are full of bullshit.“(你才满嘴屁话呢)作为自己反驳的开场白。接着,他先转向了对C++的罕见的火药味十足的炮轰:
”C++是一种糟糕的(horrible)语言。而且因为有大量不够标准的程序员在使用而使情况更糟,以至于极容易产生彻头彻尾的垃圾(total and utter crap)。老实说,选择C就是为了把C++程序员踢出去。……我有这样的结论,任何喜欢用C++而不是C开发项目的程序员可能都是我希望踢出去的人,免得他们来搞乱我参与的项目。C++会导致非常非常糟糕的设计选择。你们这些C++程序员总是一上来就用语言的那些‘漂亮的’库特性比如STL、Boost 和其他彻头彻尾的垃圾,这可能对你们的程序有所‘帮助’,但是却会导致:
“——当库无法工作时无穷无尽的折磨(别跟我说什么STL尤其是Boost很稳定而且可移植性很好,那全是屁话,而且一点都不可笑)
"——低效的抽象编程模型,可能在两年之后你会注意到有些抽象效果不怎么样,但是所有代码已经依赖于围绕它设计的‘漂亮’对象模型了,如果不重写应用程序,就无法改正。
”也就是说,使用优秀的、高效的、系统级的和可移植的C++的唯一方式,最终还是限于使用C本身具有的所有特性。项目限制只用C,意味着参与的人不会捣乱,也意味着会得到许多真正懂得底层问题,而不会折腾那些白痴‘对象模型’垃圾的程序员。
"所以,我很抱歉,但是对于Git这样效率是主要目标的软件,C++的所谓优点只是巨大的错误。而我们将看不到这一点的人排除在外却成了一个巨大的附加优势。
"如果你想要用C++写的版本控制系统,去玩Monotone吧。他们确实使用了‘真格的数据库’,使用了‘漂亮的面向对象库’、使用了‘漂亮的C+ +抽象’。可是说老实话,所有这些对某些计算机专业人士而言富于吸引力的设计决定,其最终结果确是一堆可怕、难以维护的垃圾。"
老实说,Linus Torvalds近日的言辞虽然激烈,但其实话糙理不糙。
时至今日,在一般的场合下,C和C++语言的主要用途就是系统级软件的开发。具体地说,C/C++写平台、工具和基础库,支持高层的语言来完成应用逻辑。 在9月份《程序员》杂志上刊登的一篇《微软架构师谈编程语言发展》的文章里,Brian Beckman直截了当地说,C++语言主要是用来开发别的语言的。这话片面一点,如果改成 “C++语言主要是用来支持别的语言的”,那就大体没错了。
做系统软件开发的时候,重要的是理解系统的运作方式,那些漂亮的抽象手法和高级特性是次要的。
有一个有趣的现象,不少做系统软件的老手,在用过一段C++之后,又回到C。因为在这个层次上,C++对于C的优势就不突出了。那些高级的抽象结构往往是 不必要的,反而是由于抽象层次的提高,使得开发者要弄清楚“下面实际发生的事情”变得不太容易了。所以很多老手实际上觉得用C语言控制力更强一些,更得心 应手一些。真正的C语言高手,对于语言和编译器都很熟悉了,基本上在写C时候就已经知道编译器优化以后产生汇编代码是个什么样子,甚至可以改变C代码来引 导编译器产生最优化的机器码。而C++的机制很丰富,很多机制是为了满足高层应用和框架的需求而准备的,在这个层次上发挥不出来,反而把清晰性给牺牲掉 了。很多时候,一个简单的语句,到底背后会发生什么,即使是老手也说不清。比如:
std::string s(“Linux Torvalds");
std::string scopy = s;
上面这段代码不过是创建两个内容相同的字符串副本,但是没有任何一个人能够在不了解更多信息的情况下清楚地描述背后所发生的事情,因为不同的STL对于 string的实现方式不同,因此在copy assignment时表现也不同,有的可能是简单地复制字符串对象,有的可能具有ref-counting机制,需要创建对象、设定对象值、增加引用计 数,有的没有考虑线程安全性,有的考虑了线程安全性,还得加锁解锁,对不起,加解锁也还有很多做法。创建新的string对象时,有时还需要调用内存分配 器,而这个东西的实现又五花八门,有的直接new char[],有的从内建的memory pool申请,memeory pool是不是线程安全的?对不起,这次可能又要涉及加解锁问题。memeory pool会不会已经满了?要不要次第调用new/malloc申请新的内存块?总之,后面的事情够多够复杂,没有相当功力,对平台了解不够深入,很难说出个子午卯酉来。
一个字符串复制尚且如此,别的高级特性就更不用说了。所以很多人宁可麻烦一点,也不愿意使用C++,这还是可以理解的。
就我个人来说,我还是愿意用C++的,特别是在C里写一遍又一遍realloc的时候,就想起 string::operator+=()的好处来了。大概是STL给我的印象太深了,写算法程序的时候,不用STL就觉得不爽,一个transform 就可以搞定的事情,非要用for循环,这会让我感觉浑身不自在。所以一般情况下,拿到一个什么问题,我还是会用C++去解决的。对我来说, Torvalds的话其实是很中肯的,即使是用C++,也要尽可能搞清楚其背后发生的事情,这样在写low level程序的时候才会有把握。如果是设计应用级别的程序,就尽可能不用C/C++,把底层的事情都忘掉,专心专意做好应用层的设计才是正道。
|