《高質量C/C++程式設計指南》學習筆記
這本書只有短短100頁,可是卻可以稱得上是膾炙人口。一年前初讀此書時就感覺受益良多,而今再次重讀,仍然不肯停頓一口氣讀完。針對書中指出的一些程式設計規則和建議,摘錄下個人認為比較好的部分。
用 #include <filename.h> 格式來引用標準庫的標頭檔案(編譯器將從標準庫目錄開始搜尋)。
用 #include “filename.h” 格式來引用非標準庫的標頭檔案(編譯器將從使用者的工作目錄開始搜尋)。
if、for、while、do等語句自佔一行,執行語句不得緊跟其後。不論執行語句有多少都要加{}。這樣可以防止書寫失誤。
儘可能在定義變數的同時初始化該變數(就近原則)。
長表示式要在低優先順序操作符處拆分成新行,操作符放在新行之首(以便突出操作符)。拆分出的新行要進行適當的縮排,使排版整齊,語句可讀。
命名規則儘量與所採用的作業系統或開發工具的風格保持一致。
例如Windows應用程式的識別符號通常採用“大小寫”混排的方式,如AddChild。而Unix應用程式的識別符號通常採用“小寫加下劃線”的方式,如add_child。別把這兩類風格混在一起用。
變數的名字應當使用“名詞”或者“形容詞+名詞”。
假設布林變數名字為flag,它與零值比較的標準if語句如下:
假設整型變數的名字為value,它與零值比較的標準if語句如下:
應當將指標變數用“==”或“!=”與NULL比較。
指標變數的零值是“空”(記為NULL)。儘管NULL的值與0相同,但是兩者意義不同。假設指標變數的名字為p,它與零值比較的標準if語句如下:
不要忘記最後那個default分支。即使程式真的不需要default處理,也應該保留語句 default : break; 這樣做並非多此一舉,而是為了防止別人誤以為你忘了default處理。
return語句不可返回指向“棧記憶體”的“指標”或者“引用”,因為該記憶體在函式體結束時被自動銷燬。例如
不要忘記為陣列和動態記憶體賦初值。防止將未被初始化的記憶體作為右值使用。
避免陣列或指標的下標越界,特別要當心發生“多1”或者“少1”操作。
動態記憶體的申請與釋放必須配對,防止記憶體洩漏。
用free或delete釋放了記憶體之後,立即將指標設定為NULL,防止產生“野指標”。
注意當陣列作為函式的引數進行傳遞時,該陣列自動退化為同型別的指標。
malloc返回值的型別是void *,所以在呼叫malloc時要顯式地進行型別轉換,將void * 轉換成所需要的指標型別。
用malloc申請一塊長度為length的整數型別的記憶體,程式如下:
(1)相同的範圍(在同一個類中);
(2)函式名字相同;
(3)引數不同;
(4)virtual關鍵字可有可無。
覆蓋是指派生類函式覆蓋基類函式,特徵是:
(1)不同的範圍(分別位於派生類與基類);
(2)函式名字相同;
(3)引數相同;
(4)基類函式必須有virtual關鍵字。
引數預設值只能出現在函式的宣告中,而不能出現在定義體中。
關鍵字inline必須與函式定義體放在一起才能使函式成為內聯,僅將inline放在函式宣告前面不起任何作用。
例如
偷懶的辦法處理拷貝建構函式與賦值函式
偷懶的辦法是:只需將拷貝建構函式和賦值函式宣告為私有函式,不用編寫程式碼。
當心那些視覺上不易分辨的操作符發生書寫錯誤。我們經常會把“==”誤寫成“=”,象“||”、“&&”、“<=”、“>=”這類符號也很容易發生“丟1”失誤。然而編譯器卻不一定能自動指出這類錯誤。
變數(指標、陣列)被建立之後應當及時把它們初始化,以防止把未被初始化的變數當成右值使用。
當心變數的初值、預設值錯誤,或者精度不夠。
當心資料型別轉換髮生錯誤。儘量使用顯式的資料型別轉換(讓人們知道發生了什麼事),避免讓編譯器輕悄悄地進行隱式的資料型別轉換。
當心變數發生上溢或下溢,陣列的下標越界。
當心忘記編寫錯誤處理程式,當心錯誤處理程式本身有誤。
當心檔案I/O有錯誤。
避免編寫技巧性很高程式碼。
不要設計面面俱到、非常靈活的資料結構。
如果原有的程式碼質量比較好,儘量複用它。但是不要修補很差勁的程式碼,應當重新編寫。
儘量使用標準庫函式,不要“發明”已經存在的庫函式。
儘量不要使用與具體硬體或軟體環境關係密切的變數。
把編譯器的選擇項設定為最嚴格狀態。
第1章 檔案結構
為了防止標頭檔案被重複引用,應當用ifndef/define/endif結構產生預處理塊。用 #include <filename.h> 格式來引用標準庫的標頭檔案(編譯器將從標準庫目錄開始搜尋)。
用 #include “filename.h” 格式來引用非標準庫的標頭檔案(編譯器將從使用者的工作目錄開始搜尋)。
第2章 程式的版式
一行程式碼只做一件事情,如只定義一個變數,或只寫一條語句。這樣的程式碼容易閱讀,並且方便於寫註釋。if、for、while、do等語句自佔一行,執行語句不得緊跟其後。不論執行語句有多少都要加{}。這樣可以防止書寫失誤。
儘可能在定義變數的同時初始化該變數(就近原則)。
長表示式要在低優先順序操作符處拆分成新行,操作符放在新行之首(以便突出操作符)。拆分出的新行要進行適當的縮排,使排版整齊,語句可讀。
第3章 命名規則
識別符號應當直觀且可以拼讀,可望文知意,不必進行“解碼”。命名規則儘量與所採用的作業系統或開發工具的風格保持一致。
例如Windows應用程式的識別符號通常採用“大小寫”混排的方式,如AddChild。而Unix應用程式的識別符號通常採用“小寫加下劃線”的方式,如add_child。別把這兩類風格混在一起用。
變數的名字應當使用“名詞”或者“形容詞+名詞”。
第4章 表示式和基本語句
不可將布林變數直接與TRUE、FALSE或者1、0進行比較。假設布林變數名字為flag,它與零值比較的標準if語句如下:
if (flag) // 表示flag為真
if (!flag) // 表示flag為假
應當將整型變數用“==”或“!=”直接與0比較。假設整型變數的名字為value,它與零值比較的標準if語句如下:
if (value == 0)
if (value != 0)
不可模仿布林變數的風格而寫成if (value) // 會讓人誤解 value是布林變數
if (!value)
不可將浮點變數用“==”或“!=”與任何數字比較。應當將指標變數用“==”或“!=”與NULL比較。
指標變數的零值是“空”(記為NULL)。儘管NULL的值與0相同,但是兩者意義不同。假設指標變數的名字為p,它與零值比較的標準if語句如下:
if (p == NULL) // p與NULL顯式比較,強調p是指標變數
if (p != NULL)
每個case語句的結尾不要忘了加break,否則將導致多個分支重疊(除非有意使多個分支重疊)。不要忘記最後那個default分支。即使程式真的不需要default處理,也應該保留語句 default : break; 這樣做並非多此一舉,而是為了防止別人誤以為你忘了default處理。
第5章 常量
在C++ 程式中只使用const常量而不使用巨集常量,即const常量完全取代巨集常量。第6章 函式設計
const資料成員的初始化只能在類建構函式的初始化表中進行,例如 class A
{…
A(int size); // 建構函式
const int SIZE ;
};
A::A(int size) : SIZE(size) // 建構函式的初始化表
{
…
}
A a(100); // 物件 a 的SIZE值為100
A b(200); // 物件 b 的SIZE值為200
如果引數是指標,且僅作輸入用,則應在型別前加const,以防止該指標在函式體內被意外修改。return語句不可返回指向“棧記憶體”的“指標”或者“引用”,因為該記憶體在函式體結束時被自動銷燬。例如
char * Func(void)
{
char str[] = “hello world”; // str的記憶體位於棧上
…
return str; // 將導致錯誤
}
第7章 記憶體管理
用malloc或new申請記憶體之後,應該立即檢查指標值是否為NULL。防止使用指標值為NULL的記憶體。不要忘記為陣列和動態記憶體賦初值。防止將未被初始化的記憶體作為右值使用。
避免陣列或指標的下標越界,特別要當心發生“多1”或者“少1”操作。
動態記憶體的申請與釋放必須配對,防止記憶體洩漏。
用free或delete釋放了記憶體之後,立即將指標設定為NULL,防止產生“野指標”。
注意當陣列作為函式的引數進行傳遞時,該陣列自動退化為同型別的指標。
malloc返回值的型別是void *,所以在呼叫malloc時要顯式地進行型別轉換,將void * 轉換成所需要的指標型別。
用malloc申請一塊長度為length的整數型別的記憶體,程式如下:
int *p = (int *) malloc(sizeof(int) * length);
第8章 C++函式的高階特性
成員函式被過載的特徵:(1)相同的範圍(在同一個類中);
(2)函式名字相同;
(3)引數不同;
(4)virtual關鍵字可有可無。
覆蓋是指派生類函式覆蓋基類函式,特徵是:
(1)不同的範圍(分別位於派生類與基類);
(2)函式名字相同;
(3)引數相同;
(4)基類函式必須有virtual關鍵字。
引數預設值只能出現在函式的宣告中,而不能出現在定義體中。
關鍵字inline必須與函式定義體放在一起才能使函式成為內聯,僅將inline放在函式宣告前面不起任何作用。
第9章 類的建構函式、解構函式與賦值函式
A(void); // 預設的無引數建構函式
A(const A &a); // 預設的拷貝建構函式
~A(void); // 預設的解構函式
A & operate =(const A &a); // 預設的賦值函式
如果類存在繼承關係,派生類必須在其初始化表裡呼叫基類的建構函式。例如
class A
{…
A(int x); // A的建構函式
};
class B : public A
{…
B(int x, int y);// B的建構函式
};
B::B(int x, int y)
: A(x) // 在初始化表裡呼叫A的建構函式
{
…
}
類的const常量只能在初始化表裡被初始化,因為它不能在函式體內用賦值的方式來初始化。偷懶的辦法處理拷貝建構函式與賦值函式
偷懶的辦法是:只需將拷貝建構函式和賦值函式宣告為私有函式,不用編寫程式碼。
例如:
class A
{ …
private:
A(const A &a); // 私有的拷貝建構函式
A & operate =(const A &a); // 私有的賦值函式
};
在編寫派生類的賦值函式時,注意不要忘記對基類的資料成員重新賦值。第10章 類的繼承與組合
若在邏輯上B是A的“一種”,並且A的所有功能和屬性對B而言都有意義,則允許B繼承A的功能和屬性。第11章 其它程式設計經驗
如果輸入引數採用“指標傳遞”,那麼加const修飾可以防止意外地改動該指標,起到保護作用。當心那些視覺上不易分辨的操作符發生書寫錯誤。我們經常會把“==”誤寫成“=”,象“||”、“&&”、“<=”、“>=”這類符號也很容易發生“丟1”失誤。然而編譯器卻不一定能自動指出這類錯誤。
變數(指標、陣列)被建立之後應當及時把它們初始化,以防止把未被初始化的變數當成右值使用。
當心變數的初值、預設值錯誤,或者精度不夠。
當心資料型別轉換髮生錯誤。儘量使用顯式的資料型別轉換(讓人們知道發生了什麼事),避免讓編譯器輕悄悄地進行隱式的資料型別轉換。
當心變數發生上溢或下溢,陣列的下標越界。
當心忘記編寫錯誤處理程式,當心錯誤處理程式本身有誤。
當心檔案I/O有錯誤。
避免編寫技巧性很高程式碼。
不要設計面面俱到、非常靈活的資料結構。
如果原有的程式碼質量比較好,儘量複用它。但是不要修補很差勁的程式碼,應當重新編寫。
儘量使用標準庫函式,不要“發明”已經存在的庫函式。
儘量不要使用與具體硬體或軟體環境關係密切的變數。
把編譯器的選擇項設定為最嚴格狀態。
如果可能的話,使用PC-Lint、LogiScope等工具進行程式碼審查。
相關文章
- C++/C高質量程式設計指南-筆記C++程式設計筆記
- 《高質量C++程式設計指南》讀書筆記(一) (轉)C++程式設計筆記
- 高質量C++/C程式設計指南(林銳)C++C程式程式設計
- 高質量C++/C程式設計指南(前 言) (轉)C++C程式程式設計
- 高質量C/C++程式設計指南總結(八)—— C++高階特性C++程式設計
- 高質量C++/C程式設計指南(參考文獻) (轉)C++C程式程式設計
- 高質量C++/C程式設計指南(第5章 常量) (轉)C++C程式程式設計
- 高質量C++/C程式設計指南(附錄B :C++/C試題) (轉)C++C程式程式設計
- 高質量C++/C程式設計指南(第6章 函式設計) (轉)C++C程式程式設計函式
- 高質量C++/C程式設計指南(第2章 程式的版式) (轉)C++C程式程式設計
- 高質量C/C++程式設計指南總結(二)—— 檔案版式C++程式設計
- 高質量C/C++程式設計指南總結(三)—— 命名規則C++程式設計
- 高質量C++/C程式設計指南(第11章 其它程式設計經驗) (轉)C++C程式程式設計
- 高質量C++/C程式設計指南(第8章 C++函式的高階特性) (轉)C++C程式程式設計函式
- 高質量C++/C程式設計指南(第3章 命名規則) (轉)C++C程式程式設計
- 高質量C++/C程式設計指南(第1章 檔案結構) (轉)C++C程式程式設計
- C++高質量程式設計C++程式設計
- 高質量C++/C程式設計指南(第4章 表示式和基本語句) (轉)C++C程式程式設計
- 高質量C++/C程式設計指南(附錄C :C++/C試題的答案與評分標準) (轉)C++C程式程式設計
- 高質量C++/C程式設計指南(第10章 類的繼承與組合) (轉)C++C程式程式設計繼承
- 一道C++的題(從《高質量C++程式設計指南》中改編)(1千字)C++程式設計
- 《通過遊戲程式設計實戰教新手學C++程式設計》學習筆記遊戲程式設計C++筆記
- Javascript高階程式設計 學習筆記JavaScript程式設計筆記
- 學習筆記:物件導向程式設計技術(C++版)筆記物件程式設計C++
- 一個C++程式設計師的Delphi學習筆記 (轉)C++程式設計師筆記
- 《C++ Primer》學習筆記(六):C++模組設計——函式C++筆記函式
- C++核心程式設計筆記C++程式設計筆記
- C++學習筆記C++筆記
- CUDA C 程式設計權威指南 學習筆記:第二章 CUDA程式設計模型程式設計筆記模型
- C++學習筆記——C++ 繼承C++筆記繼承
- C/C++學習筆記:字串C++筆記字串
- C++/C學習筆記(七)C++筆記
- C/C++學習路線———學習筆記C++筆記
- c++學習筆記(三)C++筆記
- C++學習筆記——003C++筆記
- c++學習筆記(四)C++筆記
- c++學習筆記(五)C++筆記
- OI學習筆記(C++)筆記C++