儘量以const和inline取代#define

#define是屬於預處理器指令的,在Effective C++中提到的條款1的標題如果改爲“儘量以編譯器(compiler)取代預處理器(preprocessor)”或許更好,因爲#define通常不被視爲語言本身的一部分。

何爲預處理器?

預處理器是編譯器把C++代碼編譯爲機器指令之前執行的一個過程,所有的預處理器都是#開頭,以便與C++語句區分開來。

何爲#define指令?

該指令用於符號置換,其格式爲#define  標示符 字符序列。注意該語句不以分號結束。比如#define PI 3.1416就表示把PI置換爲3.1416,這裏要注意的是雖然PI看起來和變量一樣,但PI和變量沒有半毛錢的關係,PI只是一個符號或標誌,在程序代碼編譯前該符號會用一組指定的字符來代替。還要注意的是3.1416並不是一個數值,而是一個字符串,因此不會進行類型檢查。而語句中的字符序列可以是任意的字符序列,而不僅僅是數字,比如#define PI HYONG這樣的話在使用PI使就會用HYONG來替換掉PI,當然HYONG這裏會是一個未定義的標識符。

在使用#define指令定義常量時常常造成意想不到的錯誤

而在C++中可以使用const來聲名常量,比如const long double PI=3.1416;這樣的話PI將會始終保持爲long double類型。C++會對它進行嚴格的類型安全檢查。這樣就可以避免因簡單的字符替換而出現的不可預料的錯誤。

(關於這個const在面試中也是常常被問到,記得一次我遇到面試官問我const的本質是什麼,我稀裏糊塗說了大半天,他搖搖頭說沒有說到本質上去。最後他總結時說到如果你能說出const的本質是隻讀的我就不會接着問你那麼多的關於const的問題了。暈,平常還是思考的不夠細緻,沒有及時的總結,書看的少了。)

多本書(Effective C++,C/C++高質量程序設計指南)上提到的一個無用#define指令的常見例子是,以它來實現宏------看起來像函數,卻又不會帶來函數調用所需要的成本。

一個最經典的在多本書中提到的例子就是計算兩個數的最大值: #define max(a,b)  ((a) > (b) ? (a) : (b))

儘管我們可以像上面一樣通過加上括號來解決一些問題,但百密一疏,bug總還是會出現的,比如下面的用法就會讓事情很糟糕

int a = 5,b = 0;

max(++a,b);  //a會被累加2次

max(++a,b+10);   //a被累進1次

如果我們使用inline函數便可以獲得宏帶來的高效率以及函數帶來的可預期行爲和引數型別檢驗

inline int max(int a,int b)   {return a > b ? a : b;}

有時在筆試時有些考題是這樣的,讓你用宏實現交換兩個數,變態的是還不能用+,-,*,%。不知道這樣的考題有意義否?

如交換兩個數的宏可以這樣實現

#define swap(x, y)  (x = x + y, y = x - y, x = x - y )

要注意的是當輸入的數據是不同種類型的話,這個宏的結果是不對的。 

如果要求你不能使用+,-,*,%,那麼就只能用位運算中的異或來運算,當然使用位運算會有更高的效率

#define swap(x, y)  (x ^= y, y ^= x, x ^= y)

但是這種實現只適用於整型數據。

就算我們適當的加上括號來防止一些錯誤,但上面所陳述的bug還是存在的

#define swap(x,y) ((x)=(x)+(y),(y)=(x)-(y),(x)=(x)-(y))

不思則以,細細想來,寫代碼還真不是一件容易的事,寫的越多有時越痛苦,感覺語言上就那些東西自己都掌握了,寫起代碼來總是出現我們所未知的錯誤。幸好在C++中有了const和inline可以幫助我們很好的解決上面的問題,不然真不知該腫麼辦!!!!


發佈了41 篇原創文章 · 獲贊 5 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章