今年8月在HX實習時,組長要求實習生每週要進行代碼和編程知識的分享,作爲組內爲數不多的C++er,想來想去還是總結整理一下Effective C++裏的條款,也算自己再進行一遍複習。
- 過往我們在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)中,不再是“僞常量”。
- #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也支持這種方式。
- 2.中提到,static const int型的常量類內聲明定義或者類內聲明+類外定義都可以,但是如果我們還需要該常量來說明類內一個數組的長度時,就必須執行類內聲明+定義了:
class Game
{
static const int len = 5;
int nums[len];
}
However,有些老式編譯器卻又不支持上述的類內初始化,那該怎麼辦呢?我們可以使用enum來充當類內常量:
class Game
{
enum{ len = 5};
int nums[len];
}
- 使用#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