條款一 C++是一個語言聯邦
建議
- c++是有兄弟的:C,Object-Oriented c++(c with class),template c++,STL
- c++高效編程守則視狀況而變化,取決於你使用c++的哪一部分。
條款二 盡量使用const, enum, inline代替define。
-
寧可編譯器替換預處理器比較好。因為define不被視為語言的一部分。
define NUM 3
define在預處理器中已經替換成為具體的值,當編譯遇到一個常量錯誤的時候,你可能會感到困惑,因為錯誤信息提到的可能是3,而不是NUM。
而且當NUM的定義不是你所設計的時候,你可能會因為去查找3這個值所引發的錯誤到底是為什么而頭大!這個問題也可能出現在記號調試器(symbolic debugger)中,原因相同:你所使用的名稱可能並未進入記號表(symbol table)
另一個原因是:const可以成為作用域中的一個成員,define並不能行,且不能提供任何封裝性。
還有一個原因是#define的函數#define MAX(a,b) func((a)>(b)?(a):(b)) int a=5,b=0; MAX(++a,b); //a被累加二次 MAX(++a,b+10); //a被累加一次
在這里,調用f之前,a的遞增次數不定!
建議用內聯模板
建議
- 對於單純常量,最好以const對象或者enum替換#define
- 對於形似函數的宏,最好改用inline函數替換
條款三 盡量使用const。
-
const在常量中的運用。
char greet[] = "hello"; const char* p = greet; //const data,non-const pointer; char* const p = greet; //non-const data,const pointer; const char* const p = greet; //const data,const pointer;
迭代器中:
vector<int>vec; const vector<int>::iterator iter = vec.begin(); *iter = 10; //沒問題,改變iter所指的實體; ++iter; //錯誤!iter是const //其實看過const_iterator的實現就知道,他就是對實體對象的一個const vector<int>::const_iterator citer = vec.begin(); *citer = 10; //錯誤!*citer是const; ++citer; //沒問題!改變citer
-
const在函數中的運用
const Rational operator*(const Rational &lhs);
避免用戶XJBY。
-
const成員函數
第一,他們使得class接口比較容易理解,可以知道哪個函數可以改動對象內容,哪個函數不行。
第二,他們使得“操作const對象”成為可能。 -
編譯器強制實施bitwise constness,但你編寫程序時應該使用概念上的常量性
-
當const和non-const成員函數有着實質等價的實現時,令non-const版本調用const版本可避免代碼重復。但是要做好類型轉換,否則會出現自己調用自己的現象。
const char& operator[] (int position) const { return m_text[position]; } /* 返回類型是個reference to char,不是char */ char &operator[](int position) { return m_text[position]; /*調用const operator[]*/ /* return const_cast<cahr&>(const TextBlock&)(*this)[position]); */ }
建議
- const真的是一個磨人的小妖精
條款四 確定對象在使用前已經初始化。
-
為內置型對象進行手工初始化,因為C++不保證初始化它們。
-
構造函數最好使用成員初始化列表(member initialization list),而不要在構造函數本體內使用賦值操作(assignment)。初值列列出的成員變量,其排列次序應該和它們在class中的聲明次序相同。
C++規定,對象的成員變量的初始化動作發生在進入構造函數本體之前。構造函數體內的“=”叫做“賦值”,初始化發生的時間更早,發生於這些成員的default構造函數被自動調用之時。
賦值構造的實質是:先設定初值,再為它們賦予新值。
成員列表初始化:避免上述問題,同時避免調用copy構造函數,高效很多 -
為免除“跨編譯單元之初始化次序”問題,請以local static對象替換non-local static對象。(不是很明白)
建議
- 記得初始化!
- 可以使用初始化列表