Effective C++筆記:盡量以const、enum、inline替換#define
一.#define定義的類似函數(shù)的宏,使用時(shí)易出錯(cuò)
缺點(diǎn)描述
這樣做的初衷是,宏看起來(lái)像函數(shù),但不會(huì)招致函數(shù)調(diào)用(function call)帶來(lái)的額外開銷。但即使你為所有實(shí)參加上小括,仍然會(huì)在使用時(shí)遭遇麻煩。舉個(gè)例子:
//?求兩個(gè)變量中最大的那個(gè) #define?THE_MAX(a,?b)?f((a)?>?(b)???(a)?:?(b))
當(dāng)這樣使用的時(shí)候:
THE_MAX(++a,?++b);
a和b總有一個(gè)會(huì)多累加一次,這是我們不希望看到的。
替代方法
可以使用template inline函數(shù),它具有堪比宏的效率和函數(shù)的類型安全性。
inline?void?THE_MAX(const?T&?a,const?T&b)
{
???f((a)?>?(b)???(a)?:?(b))
}二.#define定義的符號(hào)不會(huì)進(jìn)入記號(hào)表(symbol table),導(dǎo)致調(diào)試?yán)щy
缺點(diǎn)描述
如果有如下宏定義:
#define?PI?3.1415926
#define不被視為語(yǔ)言的一部分,PI在編譯器開始處理源碼之前就被預(yù)處理器轉(zhuǎn)移走了,于是記號(hào)PI很可能沒(méi)進(jìn)入記號(hào)表。當(dāng)使用此宏但獲得一個(gè)編譯錯(cuò)誤信息時(shí),可能會(huì)帶來(lái)困惑,因?yàn)檫@個(gè)錯(cuò)誤信息也許會(huì)提到3.1415926而不是PI。如果PI被定義在一個(gè)非你所寫的頭文件內(nèi),你肯定對(duì)3.1415926以及它來(lái)自何處毫無(wú)概念,于是你將因?yàn)樽粉櫵速M(fèi)時(shí)間。
替代方法
以一個(gè)常量替換上述的宏:
const?double?pi=?3.1415926
作為一個(gè)語(yǔ)言常量,pi肯定會(huì)被編譯器看到,當(dāng)然就會(huì)進(jìn)入記號(hào)表。此外對(duì)浮點(diǎn)常量而言,使用常量可能比使用#define導(dǎo)致較小量的碼,因?yàn)轭A(yù)處理器"盲目地將宏名稱pi替換
為3.1415926"可能導(dǎo)致目標(biāo)碼(object code)出現(xiàn)多份3.1415926,若改用常量pi絕不會(huì)出現(xiàn)相同情況。
有兩個(gè)需要注意的地方:
(1) 當(dāng)定義的是常量指針,需要const兩次( const char* const iVar = "C++"),第一個(gè)const是防止值被改變,第二個(gè)const防止地址被改變。
(2) 當(dāng)定義到class內(nèi)時(shí),需要用static來(lái)修飾這個(gè)變量,防止出現(xiàn)多個(gè)實(shí)體,代碼如下:
class?MyClass
{
private:
???int?i;
???doubel?d;
???static?const?int?num?=?15;
???int?scores[num];
};三.#define不重視作用域(scope)的概念,破壞封裝性
缺點(diǎn)描述
一旦宏被定義,它就在其后的編譯過(guò)程中有效(除非在某處被#undef) 。這意味#define不僅不能夠用來(lái)定義class專屬常量,也不能夠提供任何封裝性,也就是說(shuō)沒(méi)有所謂private #define這樣的東西。
替代方法
class?MyClass
{
private:
???int?i;
???doubel?d;
???enum?{?num?=?15?};
???int?scores[num];
};使用enum還有個(gè)好處是,如果你不想讓別人獲得一個(gè)pointer或reference指向你的某個(gè)整數(shù)常量,enum可以幫助你實(shí)現(xiàn)這個(gè)約束,因?yàn)槿∫粋€(gè)enum的地址不合法。





