注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

天地不仁,以万物为Googol!

天行有常,不以物喜,不以己悲……

 
 
 

日志

 
 

蓦然回首:C++历史上的五组五魁首,第二组:永远最重要的五篇非书籍文章

2006-09-23 22:32:53|  分类: 翻译 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

原文:http://www.artima.com/cppsource/top_cpp_publications.html

 

作者:Scott Meyers

 

上周,在我这个系列的第一篇文章中,我列出了我认为最重要的关于C++的书籍。但是,很多很重要的关于C++的文章,并不是以书籍的形式出现的。比如在月刊、杂志和网上的文章;博士论文或研讨会报告;新闻组里的帖子;Blog里的文章;标准化文档等等。它们都扮演了推动C++发展和传播的角色。这些文章我没可能都读过。甚至其中很大一部分我都没有读过。但是,作为一个工作就是紧跟C++发展的人,我敢说我确实读了不少的这类文章。这周的列表,就是我选出的在C++历史中,最重要的五个非书籍发布文章。同时,像我在上次关于书的列表中一样,我把自己列表的数量限制在五个,并且将我自己的文章也列为候选者(虽然我的文章并没有重要到能进入列表的地步),并且我以文章出现的时间为顺序,排列这些文章。

 

这个类别使我不得不纠缠于一个难题:如果文章A包含了一个观点,但这个观点对C++界的直接影响很小,而某个人读了文章A后,借助文章A中的观点,写就了文章B,并且最重文章B产生了广泛的影响,那么,谁的文章更重要呢?A(发明的)还是B(将其推广的)?我选择B,并不是说这个选择是正确的,而是因为我不想去追究文章作者的观点,是否是继承自其他文章。(注1)我只是从C++的历史书上抽出一页。正像广为人知的,const对成员函数的修饰只是浅修饰:指针成员变量将会自动变成常量,而其所指向的东西依旧可以改变。(我觉得这里举浅拷贝的例子更好,当然意思都是一样的)下面的列表里,我所引用的文章,按我的定义,都是重要的,但是我认为这些文章所引用的文章(如果我忽略掉了的话)是不重要的。就像C++的行为一样,这样也许是不正确的,但这样简单易行。这也是我这样做的原因。(注2)

 

在开始我的列表之前,请允许我简单的缅怀一下《C++ Report》,一本永远专注于C++的期刊。(如果你看到这里觉得不舒服,可以跳过这段。)在它发行的大部分时间里(发行时间:1989年到2000年),对宣传C++的人和对C++有所动摇的人来说,《C++ Report》就是源泉。(在电子领域与其类似的是新闻组comp.lang.c++以及后来的comp.std.c++和comp.lang.c++.moderated。)曾经在《C++ Report》发表过文章的人里,包括了你肯定听说过的人(比如,在我的《最重要的五本书》中列出的书的作者)和更多的你没听说过的人(比如,下面将要列出的文章的作者,还有……这个人名列表太长了,不可能全部列举的。我试图列举了一下,但写下几个名字后,我意识到,我这样做有很大风险:暗示了列表上的人比其他不再列表上的更重要。与其那么做,我不如什么都不写。但是相信我,在这本期刊辉煌的年代里——它生命的大部分时间都很辉煌——《C++ Report》吸引了这个领域最牛的作者:那些人想告诉你很多有趣的东西,同时也确实能讲得很有趣。)当《C++ Report》关门后,很多专栏作家投奔了《C/C++ Users Journal》。但是这个期刊对我并没有那么强的吸引力。而现在,CUJ也关门了,只有像我这样的老古董们饭后闲谈时,才会怀念《C++ Report》了。

 

好了,我感觉好多了。那么,让我们开始“永远最重要的五篇非书籍文章”的列表吧。

 

蓦然回首:C++历史上的五组五魁首,第二组:永远最重要的五篇非书籍文章 - Googol - 天地不仁,以万物为Googol!

- Programming in C++, Rules and Recommendations(C++程序的规范和建议),作者:Mats Henricson和Erik Nyquist(又见奈奎斯特,想当年的《自控原理》……),Ellemtel无线电通讯实验室,1992年发布。早在我90年代的一系列老文章中,我就提到了,程序员在如何控制C++的威力方面,急需一些指导,而且他们一般更喜欢那些能告诉他们什么能做,什么不能做的编码上的指导。在我试图在《Effective C++》中给出这种指导的同时,Mats Henricson和Erik Nyquist在互联网上发布了他们的编程指导。其实这个指导早就有了,只不过是用瑞典文写的,大大限制了其指导的影响力。

 

Ellemtel的指导是彻头彻尾的技术文章,很容易阅读,并且流传很广,产生了很大的影响。很快,这篇文章要集结成书出版的消息不胫而走,而且,我也预感到这将成为事实。(市场竞争是好事,但在那时候,我确实独占了整个市场,而且我喜欢那样。(注3))一年有一年,我们盼啊盼,等啊等,终于,这本书于1996年出版了(《Industrial Strength C++》,作者:Mats Henricson和Erik Nyquist,Prentic Hell出版社,1997年出版)。但是,时不我待,等书出版时,对当时的编译器来说,指导的很多方面已经变得不再合适了,而书中的很多知识也已经在C++社区内广为流传。这本书与四年前第一次以英文出现的《规范和建议》比起来,大大的贬值了。我读了这本书,开始还有些兴趣,最后却有些悲痛,因为我觉得,四年的时间,由文档集结成书,不仅失掉了不少敏锐的技术信息,而且作品本身失去了灵魂。我猜,为了让所有的评审人对所有的内容满意,原稿不得不反复进行修改。结果导致了出版周期很长,而且文风不再犀利。

 

我怀疑,这本书的影响,比起作者的期望来说,要小很多。但这并没有减小原稿的魅力。当原稿一出现,C++社区立刻理解了整个文档。这是将C++程序设计中好的实践编纂成册的重要的里程碑。

 

蓦然回首:C++历史上的五组五魁首,第二组:永远最重要的五篇非书籍文章 - Googol - 天地不仁,以万物为Googol!

- Exception Handling: A False Sense of Security(异常处理:虚假的安全性),作者:Tom Cargill,《C++ Report》11/12月号。1994年,C++社区里弥漫着一股浮夸的气氛。C++是最热门的语言,相关的工作职位也很多,让人感到无限的可能。在这之前的一段时间,C++加入了很多很重要的语言特性:多重继承,模版,而且还最新加入了异常处理。因为异常是个全新的东西,《C++ Report》上经常能看到关于这方面的文章,而C++程序员们也热衷于在任何地方都聚集起来讨论异常。很多的文章反映了当时的浮躁:“异常太有用了。异常使处理错误情况变得非常简单。你只需要知道try,throw和catch。来吧,看看我是如何开发一个栈类,并向你演示异常使C++代码变得更好的。”Tom Cargill的文章(实际是他一系列的专栏文章,“讨厌的C++”(C++ Gadfly)——明显这是最贴切的专栏名之一)只能淹没在大家自满的笑容中。Cargill只用了一句话,就解释了try,throw和catch实际并没有什么帮助:

 

使用异常,最难的部分是用这样一种方式来写插入的代码[就是指throw和catch之间的那段代码]:任何异常都可以从抛出的地方,安全的传递到处理的地方,并且不破坏沿途的任何部分。

 

这个专栏后来对《C++ Report》上其他专栏里类似“异常太有用了”这类文章进行分析解剖(注4),并且最终导致了一场竞赛(Cargill称其为“一个邀请”):公布一个异常安全的栈类。这个挑战引起了一阵旋风似的回应,但是在我看来,直到1997年Herb Sutter的一篇文章(见下文)里的实现,其余都不能真正满足竞赛的要求。

 

Tom Cargill的专栏不仅使我们认识到我们对异常的认识还很肤浅,我想它还标志了对C++单纯无知的终结。在我们寻扎如何写出异常安全的程序时,Java正是兴盛时(而现在是Ruby on Rails)。那种毫不怀疑“我们是第一”的精神状态,也从没有真正离开我们。

 

蓦然回首:C++历史上的五组五魁首,第二组:永远最重要的五篇非书籍文章 - Googol - 天地不仁,以万物为Googol!

- Curiously Recurring Template Patterns(奇怪的模版再继承模式,…………原谅我吧,我也不知道怎么翻合适),作者:Jim Coplien,《C++ Report》1995年二月号。这篇文章的意义并不在于它的内容,而是它给这个技术起了一个名字。这真是双重的讽刺,因为这篇文章是Coplien的专栏“没有名字的专栏”(The Column Withou Name)中的一篇文章,并且他给出的这个名字简直就是所有模式中最奇怪的:奇怪的模版再继承模式(CRTP)(注5)。这个模式本身使用继承类,作为其基类模版的参数:

 

template<typename T>

class Base { ... };

 

class Derived: public class Base<Derived>

{ ... };

 

那些偏离以正常方式使用模版作为容器T的人,偶然得到了这种CRTP设计。当他们设计出这个模式后,很自然会怀疑是否能通过编译。而且,当他们(可能很惊讶的)发现确实能通过编译时,他们开始担心设计出这种东西是不是早期痴呆的症状之一。这时,Coplien出现了。之前对这个技术更有经验的同事们可以放心了:“不,你们没病。使用子类来使基类模版化,这不仅在技术上是合法的,甚至还有个名字:奇怪的模版再继承模式。”

 

蓦然回首:C++历史上的五组五魁首,第二组:永远最重要的五篇非书籍文章 - Googol - 天地不仁,以万物为Googol!

- Using C++ Template Metaprograms(使用C++模版元编程),作者:Todd Veldhuizen,《C++ Report》1995年五月号。这篇文章第一次公开描述了大规模的模版元编程(TMP)。这是个重大的机会,而我把它完全忽视了。我记得我读完了文章,思考着:“好吧,你确实可以在编译期用递归实例化模版来模拟for循环。并且利用模版特化来实现编译期switch选择状态。这些都不错,但是你想用它们干什么呢?”实际上,我在说谎。我实际想的是:“不过你确实是个疯子。”(注6)

 

结果是,一方面C++社区不断出现使我震惊的疯子,另一方面事实是越来越多的关于TMP的帖子出现在各种论坛,但是我依旧固执的人为TMP的技术太奇怪,仅仅是语法上的表达,而不会有任何实际的用处。而现在,TMP很显然已经有了广泛的应用,虽然我可以在某些方面安慰自己说:当时大部分人都认为这只是语法的特殊力量,并且,如果从原理上讲不奇怪,至少也不是主流。直到TMP技术成为了每个库开发者必备的技巧。做为轻视这门技术的忏悔,从Veldhuizen第一次写关于TMP的文章开始,我就尽全力总结这个技术和使用方法,并将其作为一个条目编入了第三版的《Effective C++》。

 

蓦然回首:C++历史上的五组五魁首,第二组:永远最重要的五篇非书籍文章 - Googol - 天地不仁,以万物为Googol!

- Exception-Safe in Generic Components(通用组件中的异常安全),作者:David Abrahams。我能查到的,这篇文章最早发布在《Proceedings of the International Seminar on Generic Programming》(关于通用组件的国际研讨会报告),德国Dagstuhl Castle出版,1998年四月27日到五月1日。但这篇文章一定在1997年中期就已经出现了,因为Herb Sutter在1997年七月就引用David Abrahams的论文,作为他在——还能是哪里?——《C++ Report》上一篇文章的材料。而且,我还找到了David Abrahams在1997年四月在新闻组里发的帖子,其中引用了这篇文章(http://tinyurl.com/nk5vn),但是,很可惜,那篇文章的链接已经失效了。

 

现在,保证一个函数是异常安全的三种层次——基本保证,强保证,和无失败保证——已经广为人知。Hurb Sutter推广了这些概念,并写了很多关于这些概念的文章,但是,首先引入这些概念的,是David Abrahams的这篇文章,而且,实话实说,我认为更主要的原因是,Sutter很谨慎的认同这个事实。(注7)我想,这是一个典型的例子,一篇重要的文章最初在一个很小的范围内流传,但是,这个小范围的某个人在很多方面有重大的影响(比如,是C++的定义者之一,并且/或者负责实现标准库),因此最初的文档产生的效果就大大增强了。

 

有趣的是,虽然Abrahams的文档机械的建立起了对异常安全的理解,而这种理解是定义C++标准库的基础,但是C++标准本身却并没有提到过“基本保证”,“强保证”,或者“无失败保证”。

 

这篇列表和上一篇一起列举了重要的C++出版物,但是C++本身是个软件,因此我的下一个主题,将是五个与C++相关的最重要的软件。

 

注:

 

1 如果穷追下去,问题就更困难了(比如,B从A处得到灵感,但是A的思想来自Z,而Z又是学的Y……)。

 

2 使用简单的方式实现浅常数化,并没有什么特别的原因。更准确地说,这是作用在常数和指针上的一个一般规则的副作用。如果指针本身是常数,并不需要保证它所指向的内容*p也是常数。对常量成员函数来说,*this是常数的,但是如果p是*this的一个指针成员,并没办法确定*p是否也是常数。

 

3 更早些,另外有一个C++指南文章,Thomas Plum和Dan Saks的《C++编成指南》,Plum Hall于1991年出版,但是这本书并没有什么指引作用。我看到它已经很久了,但是回想起来,并且再次快速浏览一遍后,这本书,呃,很乏味。

 

4 我在那时也是《C++ Report》的专栏作者,而且我记得就像我选择去写关于异常的东西一样,Cargill很轻松的就在我的身上验证了他的看法。看他仅仅是按部就班的——但完全专业的——揭露同事文章的缺点,这是我经历过最痛苦的事情之一。我敢说,从那时候起,我不是唯一一个在发布前,对他的文章进行再三审查的专栏作家。

 

5 Andrei Alexandrescu,现在正在攻读计算机博士学位,已经讨论过了应该将这种模式看成F-绑定的多态(F-bounded polymorphism)个简单例子,但是他并没有使人们注意到它的建议。这很对我的脾气,因为我也是计算机博士,但是我从没听说过F-绑定的多态。“CRTP”确实是个诡异的名字,但这个名字对我的刺激比F绑定的什么东西要小多了。

 

6 文章开篇的例子实现了编译期冒泡排序,但这可能并没有什么意义。我对冒泡排序极端厌恶。对工作来说,冒泡排序不仅仅是不合适的排序算法,甚至都不应该考虑这种算法。但是这个就扯远了。

 

7 开始时,并不完全认同。Sutter并没有将发表在1997年七月号《C++ Report》的文章中提到的基本保证,强保证归功于Abrahams,但是他允许我收录在1999年的《Effective C++》CD上的文章,确实将这些概念归于Abrahams。我在出版业的经验充分告诉我,《C++ Report》上刊登的刊登的文章和Sutter给我的文章,应该是不一样的。(这里是说Sutter又重新写过么?基本没懂这个含义。)

  评论这张
 
阅读(643)| 评论(2)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017