<Effective C++>條款02:儘量以const,enum,inline替換#define

         今年8月在HX實習時,組長要求實習生每週要進行代碼和編程知識的分享,作爲組內爲數不多的C++er,想來想去還是總結整理一下Effective C++裏的條款,也算自己再進行一遍複習。

  1. 過往我們在C中定義一個常量時,往往使用#define宏定義的方式來進行。爲什麼呢?

          “const在C中不表示一個變量是常量。const只表示一個變量是隻讀的。”[1]

          爲什麼這麼說呢?我們可以舉一個簡單例子:

const int a= 100;

int *pa = &a;

*pa = 200;

printf("%d",a);
    輸出結果很有意思,是200,而非100。這是因爲在C中,const僅僅是給一個常量賦予了一個只讀的屬性,這就意味着我們可以通過一個指針“繞過”其只讀的性質,從而對它的值進行修改。一個直接的體現就是,在C中不可以使用const int型常量對數組長度進行聲明。因此,在許多C代碼中,更多的是使用#define來定義常量。

到了C++中,const聲明的常量存在於符號表(symbol table)中,不再是“僞常量”。

  1. #define無法創建類的專屬常量,當我們使用const來定義類的專屬常量時,爲了確保此常量只有一個實體,必須使其成爲一個static成員:
class Game

{

static const int len = 5;

int nums[len];

}
         ①當類內static常量爲int、char、bool類型時,我們可以在類內執行聲明+定義(如上所示),但是如果需要取其地址或者編譯器要求的話,我們此時還需要在類外(實現文件內)對該常量進行定義:

const int Game::len;//定義,位於實現文件內

        ②當類內static常量非上述類型時,就必須執行類內聲明+類外定義了:

class Game

{

static const double num ;//聲明,位於頭文件內

}

double Game::num = 8.2;//定義,位於實現文件內 


當然,int/char/bool也支持這種方式。

  1. 2.中提到,static const int型的常量類內聲明定義或者類內聲明+類外定義都可以,但是如果我們還需要該常量來說明類內一個數組的長度時,就必須執行類內聲明+定義了:
class Game

{

static const int len = 5;

int nums[len];

}


However,有些老式編譯器卻又不支持上述的類內初始化,那該怎麼辦呢?我們可以使用enum來充當類內常量:

class Game

{

enum{ len = 5};

int nums[len];

}


  1. 使用#define來定義宏是一種常見的套路:
#define  CALL_MAX(a,b) fuction((a) > (b) ? (a) : (b))

inta = 5, b = 0;


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

CALL_MAX(++a, b + 10);//a被累加1次

a的遞增次數竟取決於“它被拿來和誰比較”,這樣的特性十分隱蔽且無用。

那麼,

如何獲得類似宏定義的效率?利用inline函數:

如何獲得類似宏定義的泛型特性?利用泛型編程:

template<typenameT>

Inline void call_max(const T& a, const T&b)//獲得一整羣函數,以支持泛型

{

f(a> b ? a : b);

}


 

總結:

①對於單純常量,最好以const對象或者enum來代替#define;

②對於形似函數的宏,最好改用inline函數來代替#define;

reference:

[1]https://www.cnblogs.com/collectionne/p/6713651.html




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章