Prefer consts,enums,and inlines to #defines.
我們學習C語言的時候,經常會用到前置處理器語句,比如#define,#include,#ifdef,#endif.預先處理語句是無法被編譯器看見的,所以無法得到有效錯誤提示.比如說:
#define ASPECT_RATIO 1.653
記號名稱ASPECT_RATIO有可能沒有進入記號表(symbol table)內.於是當你運用此常量獲得一個編譯錯誤資訊時,錯誤資訊的提示會提到1.653而不是ASPECT_RATIO,如果ASPECT_RATIO被定義在一個非自己寫的標頭檔內,這樣我們就需要花費時間去追蹤錯誤.但想想是不是真的需要花費這樣子的時間來糾正錯誤哪?其實用const替換#define就可以解決這個問題.
const double AspectRatio=1.653;
因為const會被編譯器看到,當然就會進入記號表內.錯誤提示的時候也就能很快的定位錯誤.
另外使用const還能產生比使用#define更小的碼.因為前置處理器盲目的將所有的ASPECT_RATIO替換為1.653,而改用常量則不會出現這種情況.
常量替換#defines的特殊情況:
(1)定義常量指標
(2)class專屬常量:範圍和static,範圍確保常量限制於class內.static確保此常量至多隻有一份實體.
另外,無法利用#define建立一個class專屬常量.
如果編譯器不允許"static整數型class常量"完成"in class初值設定",可改用所謂的"the enum hack"的補償做法.理論基礎是"一個屬於枚舉型的數值可權充ints被使用",例如:
class GamePlayer{
private:
enum {NumTurns=5};
int scores[NumTurns];
}
enum hack值得認識的兩個理由:
(1)enum hack的行為某方面說比較像#define而不像const.例如取地址,作用於const常量中是合法的,但作用於enum和#define就是不合法的.
(2)實用主義.
#define可以用來實現宏(macros),但宏確實有著很多缺點,比如說:
#define CALL_WITH_MAX(a,b) f((a)>(b))?(a):(b));
當使用int a=5,b=0; CALL_WITH_MAX(++a,b);調用的使用a被累加了兩次.但宏的優點也是有的,它不會招致函數調用帶來的額外開銷.
為了獲得宏帶來的效率以及一般函數的所有可預料行為和型別安全(type safety)---使用template inline代替它是很好的選擇.
而且如果你要實現一個"class內的private inline函數"#define是做不到的.
後話總結:
對於單純的常量,最好以const或者enums替換#defines
對於形似函數的宏,最好改用inline函數替換#defines