我怀疑可曾有人针对 C++软件开发人员,进行俄国生理学家 Pavlov(巴甫洛夫)的著名实验。否则谁能够解释,为什么当效率这个字眼被提起的时候,一大堆程序员就开始流口水?(译注:Pavlov,1849~1936,1904年诺贝尔生理学暨医学奖得主。他最著名的实验就是:狗一看到肉就“条件反射”地流口水。)
效率是件严肃的事情。程序如果太庞大或太迟缓,不论它的功能多么强大,都难以被用户接受。的确应该如此,毕竟软件是用来帮助我们把事情做得更好,而我们很难说愈慢代表愈好,或说 32MB 内存需求量比 16MB 更好,或说 100MB 磁盘空间需求量比 50MB 更好。此外,虽然某些程序之所以变得更大,消耗更多内存,是为了实现规模宏大雄心勃勃的计算能力,但也有太多程序,其庞大的身躯和迟缓的脚步必须归咎于不良的设计和懒散草率的编程习惯。
以 C++撰写高效程序,应该先认清一点,那就是 C++有可能对你原已存在的性能问题无能为力。如果你想写出一个高效的 C++程序,首先你必须能够写出一个高效程序。太多开发人员漠视此简单的事实。是的,循环可以手动展开,乘法可利用移位(shift)运算代替,但如果你所使用的高阶算法天生效率不彰,任何微调都影响不了大局。你可曾在线性算法适用的场合中,使用二次算法?你可曾一再计算相同数值?你可曾让“降低昂贵运算的平均成本”的机会飘然而逝?如果是,你不应该惊讶你的程序被视为次级景点——虽然值得一看,但还是等有多余的时间再说吧。
本章以两个角度对“效率”主题发动攻击。第一个角度和程序语言无关,其相关讨论适用于任何程序语言。针对书中所列的观念,C++有一个极佳的实现媒介:由于它对封装(encapsulation)的强力支持,我们有可能将低效率的 class 实现品以相同接口但拥有较佳算法和数据结构的新产品取代。
第二个角度和 C++本身有强烈关系。高性能算法和数据结构虽然很棒,但是草率的实现过程却会严重降低其影响力。最阴鸷险恶的错误就是“产生和销毁过多对象”,这不但容易形成,而且不容易被辨识出来。多余对象的构造动作和析构动作像是程序性能的大出血,每次一有非必要的对象被产生和被销毁,便流失宝贵的CPU 时间。这个问题在 C++程序中是如此普遍,我特别为它贡献 4个各自独立的条款,分别描述非必要的对象究竟来自何处,以及如何消除它们而又不损害程序的正确性。
程序变大和变慢,并不只因为产生太多对象。高性能道路上的其他坑坑洞洞还包括程序库的选用及语言特性的施行。以下各条款中,我也会讨论到这些题目。
读过本章内容之后,你将对改善性能的数个原则(几乎适用于任何程序)有所熟悉,你将确切知道如何阻止非必要的对象在程序中蔓延,对于编译器如何产生可执行文件,也会有更敏锐的了解。
有人说预先注意就是预先武装。若是如此,请把以下信息视为战斗前的准备。