《Effective C++ 中文版 第三版》讀書(shū)筆記
條款02:盡量以 const占婉,enum泡嘴,inline 替換 #define
簡(jiǎn)單地說(shuō)就是“寧可用編譯器替換預(yù)處理器”,因?yàn)榛蛟S #define 不被視為語(yǔ)言的一部分逆济。這正是問(wèn)題所在酌予,例如:
#define ASPECT_RATIO 1.653
記號(hào)名稱(chēng) ASPECT_RATIO 也許未被編譯器看見(jiàn)磺箕;也許在編譯器開(kāi)始處理源碼之前它就被預(yù)處理器移走了。于是記號(hào)名稱(chēng) ASPECT_RATIO 有可能沒(méi)有進(jìn)入記號(hào)表(symbol table)內(nèi)抛虫。于是當(dāng)你運(yùn)用此常量但卻獲得一個(gè)編譯錯(cuò)誤的信息時(shí)松靡,可能會(huì)帶來(lái)困惑,因?yàn)檫@個(gè)錯(cuò)誤信息也許會(huì)提到 1.653 而不是 ASPECT_RATIO建椰。如果 ASPECT_RATIO 被定義在一個(gè)不是我們自己寫(xiě)的文件內(nèi)雕欺,我們肯定對(duì) 1.653 以及它來(lái)自何處毫無(wú)概念,于是我們將因?yàn)樽粉櫵速M(fèi)大量不必要的時(shí)間棉姐。
解決之道是用常量替換上述的宏(#define):
const double ASPECT_RATIO = 1.653屠列;
作為一個(gè)語(yǔ)言常量,ASPECT_RATIO 肯定會(huì)被編譯器看到伞矩,當(dāng)然就會(huì)進(jìn)入記號(hào)表內(nèi)笛洛。此外因?yàn)轭A(yù)處理器 “盲目地將宏名稱(chēng) ASPECT_RATIO 替換為1.653” 可能導(dǎo)致目標(biāo)碼(Object code)出現(xiàn)多份 1.653,若使用常量 ASPECT_RATIO 絕不會(huì)出現(xiàn)這種情況扭吁。
當(dāng)我們以常量替換 #define 時(shí)撞蜂,
需要注意的問(wèn)題一:定義常量指針。
1.若要定義一個(gè)常量的(不變的)char*-based 字符串侥袜,你必須寫(xiě) const 兩次:
const char* const AuthorName = "Toby";
2.string 對(duì)象通常比 char*-based 更好一些蝌诡,所以上面代碼往往寫(xiě)成:
const std::string AuthorName = "Toby";
需要注意的問(wèn)題二:class 專(zhuān)屬常量。
1 為了將常量的作用域限制于class內(nèi)枫吧,你必須讓它成為class的一個(gè)成員浦旱;
2 而為確保此常量至多只有一份實(shí)體,你必須讓它成為一個(gè)static成員九杂。
class Toby {
private:
static const int AuthorAge = 30;
}
基于數(shù)個(gè)理由 enum hack 值得我們認(rèn)識(shí)颁湖。第一,enum hack 的行為某方面說(shuō)比較像 #define 而不像 const例隆,有時(shí)候這正是我們需要的甥捺。例如取 const 的地址是合法的,但取一個(gè) enum 的地址就不合法镀层,而取一個(gè) #define 的地址通常也不合法镰禾。如果你不想讓別人獲得一個(gè) pointer 或 reference 指向你的某個(gè)整數(shù)常量,enum 可以幫你實(shí)現(xiàn)這個(gè)約束唱逢。enum 和 #define 一樣絕不會(huì)導(dǎo)致非必要的內(nèi)存分配吴侦。
有了 const、enum 和 inline坞古,我們對(duì)于處理器(特別是 #define)的需求降低了备韧,但并非完全消除。#include 仍是必需品痪枫,而 #ifdef/#ifndef 也繼續(xù)扮演控制編譯的重要角色织堂。目前還不是預(yù)處理器全面隱退的時(shí)候叠艳,但是我們應(yīng)該明確地將它們壓在箱子底盡量不要用它們。
請(qǐng)記着跬Α:
1 對(duì)于單純常量虑绵,最好以 const 對(duì)象或 enum 替換 #define
2 對(duì)于形似函數(shù)的宏(macro),最好用 inline 函數(shù)替換 #define