寫在前面:

最近吃了安利開始啃Scott Meyers的Effective C++第三版,書中乾貨不少,非常值得深思借鑑。但是也有點太多了(→_→),腦子實在裝不下,就想寫成部落格一樣的讀書筆記同時分享給大家,再也是為了第二次讀的時候,能給自己留一點印象。

一共有55篇,希望自己可以堅持下來。如果有不恰當之處,還請大家及時指出。以及我會保持語言簡練,不過多解釋相關概念,因此適合對C++有一定基礎的讀者。

本篇關鍵詞: 全域性變數,宏(#define)

守則01:把C++看做一個語言的集合,而不是單一的語言

“C++ is a federation of languages”

早期的C++只是叫“C with classes”,但發展到今天已經成為一個多重泛型程式語言(Multi-paradigm programming language),它具有4種“子語言”:

C

面向物件的C++

模板C++

STL

高效的C++程式設計守則取決於你所使用的“子語言”

例如

:

在C中,一般使用值傳遞 (Pass by value)

在面向物件的C++和模板C++中,使用常量引用傳遞 (Pass by const reference)更加高效

對於STL,因為迭代器是基於指標構造而成,直接使用值傳遞即可

在不同的“子語言”中需要你用不同的策略,而非自始至終單一的方法,記住這一點對於理解學習C++這樣功能強大的語言十分有幫助

守則02:儘量使用const, enum, inline, 減少宏變數#define的使用

①或者說,儘量多用編譯器,少用預處理器

“Prefer the compiler to the preprocessor”

例如:

#define A 1。653

在上面這個語句中,字串‘A’是不會被編譯器看到的,而編譯器看到的是‘1。653’,這就會導致在除錯過程中,編譯器的錯誤資訊只顯示‘1。653’而不是‘A’,讓你不知從何下手。

解決方法:定義全域性常量

const double A = 1。653;

使用全域性常量還有一個好處:預處理器只會把每次對‘A’的引用變成‘1。653’而不管其是否已經存在,這就導致多次引用‘A’會造成多個重複物件出現在目的碼中(Object code),造成資源浪費。

②當定義或宣告全域性變數時,常數指標和類的常數需要另加考慮

對於指標

對於指標要把指標本身和它指向的資料都定義為const,例如

const char* const myWord = “Hello”;

在C++中可以更方便地使用std::string這樣基於char*型別的推廣,例如

const std::string myWord(“Hello”);

對於類的常數

宣告為類的私有靜態成員,這樣既保證變數只能被這個類的物件接觸到,又不會生成多個複製

class Player{

private:

static const int numPlayer = 5;

……。。

注意

,因為此處是類的成員聲明範圍內,所以上面只是變數的宣告和初始化,而並非定義,因此如果想獲取變數的地址,需要在別處另加定義。這個定義不能有任何賦值語句,因為在類內已經規定為const:

const int Player::numPlayer;

③列舉技巧

(the enum hack):

試想當你在一個類內宣告某變數,但你的編譯器不允許在宣告時賦值初始化,同時接下來的某個語句卻需要用到這個變數的具體數值,例如:

int noPlayer;

int scores[noPlayer];

此時編譯器便會報錯,需要在編譯期間noPlayer有具體數值,這個時候就需要使用如下技巧:

enum {noPlayer = 5};

int scores[noPlayer];

這樣編譯器就能順利透過,因為enum可以被當成int型別來使用

但注意enum型別在記憶體中沒有實體,無法取得enum型別的地址,因此這個方法更相當於取一個本地的#define數值

④對於#define的宏函式,儘量使用inline修飾的函式來代替#define

inline關鍵字用來建議編譯器把某頻繁呼叫的函式當做行內函數,即在每次函式呼叫時,直接把函式程式碼放在函式呼叫語句的地址,減少堆疊浪費。

如果為了減少堆疊資源的使用,把某個頻繁呼叫的函式規定為宏,例如用a和b的最大值來呼叫某函式f:

#define CALL_MAX(a,b) f((a) > (b) ? (a) : (b))

但這樣的做法其實相當不好,因為第一需要把所有引數用小括號擴起來,這樣的程式碼相當不雅觀,而且也會導致未知的結果:

int a=5, b=0;

CALL_MAX(++a, b); //a增加了一次

CALL_MAX(++a, b+10); //a增加了兩次

解決方法:

template

inline void callMax(const T& a, const T& b){

f(a>b ? a:b);

}

這樣既保證了堆疊不會枯竭,又讓程式碼更加美觀

總結:宏常量用全域性的const或者enum來替換,宏函式用inline修飾的函式來替換