《深入浅出C++(第2版)》作者原文:Top Ten Tips for Correct C++ Coding

6:使用using语句,特别是小程序

严格来说,常见的数据流(data-stream)对象cin和cout都是命名空间std的成员,要求按如下形式编写代码:

std::cout << "Hello." << std::endl;

真是多此一举啊!对绝大部分编程来说,我强烈推荐引入整个std命名空间,这样在cin、cout等前面就不必使用std::了。只消把下面这行放在每个程序开头:

using namespace std;

7:慎用全局变量,除用于函数间通信

这一条不用太多解释。程序员有时会自问该把变量声明成局部的还是全局的。规则很简单:如果变量是用来储存函数间通信用的信息,要么把这个变量作为参数(参数列表的组成部分),明确第传递这一信息,要么把变量弄成全局的。

要在几个函数间共享信息时,通常最实用的做法就是用全局变量表示。在语法层面上,这就意味着这些变量要在所有函数定义之外声明。

尽量少用全局变量的理由很明确:对于全局变量,一个函数的内部行为可能会且往往是无意地干扰其他函数的内部行为,这种大型程序里尤其明显。因此尽可能将绝大部分变量声明为局部的。毋庸赘言。

8:在for语句里使用局部变量

除去最古老的版本,在其他版本的C++中,局部化变量的最简方式是在for语句内部声明循环变量。该特性不是一开始就有的,因此我这样的老手还是会不时提醒你一下。

for (int i = 1; i <= n; i++) {  // 在循环内部声明i.
    cout << i << " ";           // 打印数字1到n.
}

对for循环而言,程序在循环之后很少会用到循环变量i的最终值(当然有时会用到)。一般来说,你会将诸如i的变量用作循环计数器,用完之后就丢掉。将i声明成循环内的局部变量不仅能有效节省一定的空间,也是更安全的编程方式。

这么使用for语句的一个好处是它会自动负责局部变量i的初始化。没错,它可能是多此一举,不过初始化局部变量是你应该做的,但如果函数的第一条语句是设定这个变量的值,该变量很可能未被初始化。不管怎样,最正确的程序应该像下面这样初始化局部变量:

void do_stuff() {
    int n = 0;   // 重复次数.
    int i = 0;   // 循环计数器.

注意,已初始化全局变量(包括对象)均为零值,而未初始化局部变量(包括对象)则包含无用信息,这里的无用信息是个技术术语,表示“无意义、无用值,有可能扰乱你的程序”。

9:切忌杯弓蛇影,滥用类和对象

这一条是概括性的理念指引。人们开始用C++编程时,常被告诫要将所有数据结构写成类,每个函数都弄成类的成员。

不过,上世纪90年代和本世纪初大肆宣传的面向对象程序设计(OOP),最近几年遭到一些抵触。事实上,对于只有控制台输出的简短程序,几乎找不到实例,证明类和对象能够缩减编程工作。相反,画蛇添足使用了类的程序反而占用更多空间。

那么,干嘛要用类呢?想想吧,面向对象的概念最早是由提出图形用户界面(GUI)的那班人搞出来的,既不是微软,也不是苹果公司,尽管他们声称是自己提出来的。这两种技术都起源于帕洛阿尔托研究中心(PARC)。

因此,一点都用不着惊讶,类和对象在图形或事件驱动的系统中用得最多,最得当。对象或类的实例是包含状态和行为的完整数据项,意味着它知道如何响应服务请求。这对GUI模型再合适不过了。

除此之外,我建议你掌握类和对象语法基础,这样就可以充分利用标准模板库(STL,Standard Template Library)。STL提供了大量丰富的功能,包括字符串、链表和栈等,可以简化许多编程任务。

10:类声明结尾用分号,函数结尾不用分号

一旦开始定义类,可别被语法搞晕了。

BASIC程序员有时会抱怨,“我可不想为什么时候用分号而费神。”这使得他们不喜欢Pascal。C和C++稍稍好些,至少分号(;)不是语句分隔符,只是语句终止符,用途始终如一。

但复合语句不用分号结束:

if (a == b) {
    cout << "a and b are equal.";
}

总的来说,规则就是用分号结束每个语句,但右大括号后面不能跟分号。因此,函数定义不是用分号结束的。

不过有一个例外:类声明(包括struct和union声明)必须用分号结束:

class Point {
  public:
    int x;
    int y;
};

在C/C++里,有关分号的完整语法规则总结如下:

  1. 用分号结束每个语句;
  2. 右大括号后面不能跟分号,但类声明除外。

小结

用C++编程(或者就此而言,可推广到所有语言)可谓是用到老,学到老。本文只给出了冰山一角;然而,在我可追溯至1980年代甚至更早的编程经历中,至少就个人而言,本文列举的问题都是反复遇到的。

其中更重要的想法是:根据需要选用正确的运算符(不要搞混=和==);关注数学运算里数据类型的作用;对while(n--)之类诱人的简写形式要格外小心;在for循环里使用局部变量;以及尽可能使用有意义的符号名。老实说,对于非常简单的程序,我有时也会图省事走捷径,不过当你投身复杂编程时,实践上述准则,也许做不到不让你心烦,但至少能帮你免掉很多麻烦。


相关文章:

本文参加 Translate Geeks to Chinese 翻译活动