正確編寫C++程式碼的十大要訣(2)

veldts發表於2011-11-06

《深入淺出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 翻譯活動

相關文章