Effective C++ —— 條款02

條款02:儘量以const,enum,inline替換#define

const替換#define

這個條款的另一個意思就是使用編譯器替換預編譯器,我們知道#define的內容都發生在預編譯時期,所以有時稍不留神就會出錯。

比如你寫了下面這個代碼:

#define PI 3.1415

 PI這個記號可能從未被編譯器看見,它可能在編譯器處理源碼之前就被預編譯器移走了,而且如果因爲這個常量而報錯的話,錯誤信息會提到3.1415出錯,而不是PI。

解決方法就是,將代碼改爲:

const double Pi = 3.1415;//一般宏名稱通常全部大寫,這裏改變寫法,便於區別

使用常量會比使用#define生成更少的碼,應爲預編譯器會盲目的把PI都替換爲3.1415,這樣目標碼就會出現多份3.1415,而常量Pi不會發生這種情況。

另外,當你使用常量字符串時,應該使用兩個const(爲什麼這樣用,條款03會詳細說明)

const char* const name = "Jack";

當然更推薦你使用string類

const std::string name("Jack");

 

還有一個值得注意的是class專屬常量,爲了使常量的作用域限制於class內,就要使常量成爲成員常量,而爲了使此常量至多有一份實體,就必須讓他成爲static成員。

class GamePlayer{
    private:
        static const int NumTurns = 5;//定義常量
        int scores[NumTurns];//使用常量
};

如果你要在外部文件取得他的話,只需要寫

const int GamePlayer::NumTurns;

因爲NumTurns已經有了初始值,所以不用繼續賦值。

enum替換#define

你也可以使用enum枚舉

#include<iostream>
class GamePlayer{
    private:
        enum{
        	NumTurns = 2;
		};
        int scores[NumTurns];//使用常量
};

我們把這種叫做enum hack,它在行爲方面更像一個#define而不像const,取一個const的地址是合法的,但是enun和#define的就是不合法的。

inline替換#define

對於一個比較大小的宏函數,通常寫法如下:

 

#define CALL_WITH_MAX(a, b) ((a) > (b) ? (a) : (b))

首先從書寫方法上面就可以看出十分繁瑣,而且有時還會發生不可避免的錯誤,例如下面這樣調用:

int a = 5, b = 0;
CALL_WITH_MAX(++a, b);//a被累加兩次
CALL_WITH_MAX(++a, b+10);//a被累加一次

爲了防止這種錯誤,我們可以使用template inline函數

template<typename T>
inline T& callWithMax(const int& a, const int& b){
    return a > b ? a : b;
}

總結

請記住:

  • 對於單純常量,最好以const或者enums替換#defines
  • 對於函數形式的宏,最好改用inline函數替換#defines;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章