1. 程式人生 > >Effective C++筆記之二:儘量以const、enum、inline替換#define

Effective C++筆記之二:儘量以const、enum、inline替換#define

一.#define定義的類似函式的巨集,使用時易出錯
缺點描述
這樣做的初衷是,巨集看起來像函式,但不會招致函式呼叫(function call)帶來的額外開銷。但即使你為所有實參加上小括,仍然會在使用時遭遇麻煩。舉個例子:
// 求兩個變數中最大的那個
#define THE_MAX(a, b) f((a) > (b) ? (a) : (b))
當這樣使用的時候:
THE_MAX(++a, ++b);
a和b總有一個會多累加一次,這是我們不希望看到的。
替代方法
可以使用template inline函式,它具有堪比巨集的效率和函式的型別安全性。
inline void THE_MAX(const T& a,const T&b)
{
   f((a) > (b) ? (a) : (b))
}
二.#define定義的符號不會進入記號表(symbol table),導致除錯困難
缺點描述
如果有如下巨集定義:
#define PI 3.1415926
#define不被視為語言的一部分,PI在編譯器開始處理原始碼之前就被前處理器轉移走了,於是記號PI很可能沒進入記號表。當使用此巨集但獲得一個編譯錯誤資訊時,可能會帶來困惑,因為這個錯誤資訊也許會提到3.1415926而不是PI。如果PI被定義在一個非你所寫的標頭檔案內,你肯定對3.1415926以及它來自何處毫無概念,於是你將因為追蹤它而浪費時間。
替代方法
以一個常量替換上述的巨集:
const double pi= 3.1415926
作為一個語言常量,pi肯定會被編譯器看到,當然就會進入記號表。此外對浮點常量而言,使用常量可能比使用#define導致較小量的碼,因為前處理器"盲目地將巨集名稱pi替換
為3.1415926"可能導致目標碼(object code)出現多份3.1415926,若改用常量pi絕不會出現相同情況。
有兩個需要注意的地方:
(1) 當定義的是常量指標,需要const兩次( const char* const iVar = "C++"),第一個const是防止值被改變,第二個const防止地址被改變。
(2) 當定義到class內時,需要用static來修飾這個變數,防止出現多個實體,程式碼如下:
class MyClass
{
private:
   int i;
   doubel d;
   static const int num = 15;
   int scores[num];
};
三.#define不重視作用域(scope)的概念,破壞封裝性
缺點描述
一旦巨集被定義,它就在其後的編譯過程中有效(除非在某處被#undef) 。這意味#define不僅不能夠用來定義class專屬常量,也不能夠提供任何封裝性,也就是說沒有所謂private #define這樣的東西。
替代方法
class MyClass
{
private:
   int i;
   doubel d;
   enum { num = 15 };
   int scores[num];
};
使用enum還有個好處是,如果你不想讓別人獲得一個pointer或reference指向你的某個整數常量,enum可以幫助你實現這個約束,因為取一個enum的地址不合法。
--------------------- 
作者:燦哥哥 
來源:CSDN 
原文:https://blog.csdn.net/caoshangpa/article/details/79433174?utm_source=copy 
版權宣告:本文為博主原創文章,轉載請附上博文連結!