Effective C++ 摘要(一)
阿新 • • 發佈:2018-12-26
1. 當你看到賦值符號“=”時,一定要小心, 因為賦值操作也可以呼叫copy建構函式:
Widget w1;Widget w2 = w1; //呼叫copy建構函式。
Widget w3, w4;
w3 = w4 //呼叫賦值操作符。
copy 建構函式和copy賦值函式的區別是, 如果一個新物件被定義, 一定有個建構函式被呼叫,如果沒有新物件被定義, 就不會有建構函式呼叫。
2. In-class 初值設定只允許對整數常量進行, 如果你的編譯器不支援上述語法, 你可以將初值放在定義式:
class CostE{
private:
static const double dFactor; //static class 常量宣告位於標頭檔案內
};
const double CostE::dFactor = 1.11; // 位於實現檔案內
萬一編譯器不允許“static 整型class常量”進行 “in-class”初值設定, 可改用所謂的“the enum hack”補償方法。
class GamePalyer
{
private:
enum {NumTurns = 5};
int scores[NumTurns];
};
3. 巨集定義的錯誤
#define MAX(a, b) f((a) > (b)? (a) : (b))
int a = 5, b = 0;MAX(++a, b); //a被累加兩次
MAx(++a, b+10); //a被累加一次
4. const ×
const char* p = strA; //non-const pointer, const data
char* const p = strA; //const pointer, non-const dataconst char* cosnt p = strA;//cosnt pointer, const data
const 出現在星號左側, 表示被指物是常量; 如果出現在星號右側, 表示指標是常量; 如果出現在星號兩側, 表示被指物和指標兩邊都是常量。
const char* p 和 char const * p 是等價的。
5. const_iterator 就像 const T*, 迭代器所指的東西不可被改動。
6. 令函式返回一個常量值, 可以降低因客戶錯誤而造成的意外, 而又不放棄安全性和高效性。
const Rational operator* (const Rational& lhs, const Rational& rhs);返回一個const物件的好處時, 如果客戶把== 誤寫成=,那麼編譯錯誤。
Rational a, b, c;
...
if (a*b = c)
7. const 成員函式, 形式為 void func1()const, 其作用是確認該成員函式可用於const物件身上。
class A{
...
void func1();
void func2() const;
...
}
const A objA;
A objB;
objA.func1(); //非法, 因為func1是非const成員函式, 不能用於const物件。
objA.func2(); //合法, 只有const物件可以用於const函式。
objB.func2(); //合法, 非const物件也可以呼叫const函式
8. const成員函式中如果確實要修改成員變數, 則定義成員變數為mutable。
9. override operator [] 下標過載
1) [] 只能通過成員函式過載.2) [] 返回型別為reference, 如果是值, 不能修改元素。
3) [] 應該過載const成員函式版本和non-const成員函式版本, 以支援const物件的讀值操作。
10. 初始化列表
1)C++規定, 物件的成員變數初始化發生在進去建構函式本體之前, 因此,建構函式中的成員變數賦值都是賦值操作,而非初始化。
2)建構函式的最佳寫法是使用所謂的 member intialization list(成員初始化列)替換賦值操作。 成員初始化列效率更高。 因為通過賦值構造, 首先使用default建構函式為成員變數設初值, 然後再對它賦予新值。成員初始化列的做法避免了這一問題。 3)const 成員變數或reference,他們一定需要初值, 不能被賦值,。 必須使用初始化列。
11. 成員初始化次序: base 早於 derived, 成員變數總是以器宣告次序被初始化。為避免閱讀時迷惑, 在成員初始列中列各個成員時, 最好總是以宣告次序為次序。