《Effective C++》 筆記:Tips01-Tips04

Tip01C++爲一個語言聯邦

CC++是以C爲基礎,這一部分就是基礎的C,沒有模板(template),沒有異常(exceptions),沒有重載(overloading)


Object-Oritented C++:即C with Class,面向對象部分。


Template C++C++的泛型編程


STL:一個template程序庫。


編程守則:

1.對於C而言,因爲C中沒有Object的概念,因此值傳遞(pass-by-value)比引用傳遞(pass-by-reference)高效。

2.對於Object-Oritented C++Template C++,由於有了構造函數和析構函數的存在,pass-by-reference-to-const更好

3.對於STL,因爲迭代器和函數對象都是在C指針上構建的,所以舊式的C pass-by-value再次適用


Tips02:儘量以const,enum,inline代替#define

一、原因一:#define使用的名稱可能未進入記號表(symbol table),導致調試困難。


二、enum hack的用法。

在某些舊式編譯器上,可能不允許static成員在其聲明式上獲得初值。當然,可以將初值放在定義式上。

然而,class編譯期間需要一個class常量。如

class GamePlayer{
private:
static const int NumTurns = 5;
int scores[NumTurns];
}

如果編譯器不通過static const int NumTurns = 5;就需要用到enum hack

class GamePlayer{
private:
enum {NumTurns = 5};
int scores[NumTurns];
}

補充一點,初始化static成員變量。在頭文件,類定義中聲明static變量

static T sMember

然後在源文件(.cpp)定義該static變量

T Class::sMember = value


三、#define定義的函數宏,最好用inline+tepmlate替代

#define CALL_WITH_MAX f((a) > (b) > (a) : (b))
int a = 5 , b = 0;
CALL_WITH_MAX(++a, b)  a = 7;
CALL_WITH_MAX(++a, b+10)  a = 6;

a的遞增次數取決於和誰比較。

++ab++a=6a>b,返回(++a)a = 7;

++ab+10++a=6,a<b+10,返回(b), a = 6


Tip03:儘可能使用const

一、成員函數是const的含義,Class::Function() const

1.bitwise constness:成員函數不能改變任何成員變量,也就是說不能更改對象的任何一個bit

但是如果,成員變量是指向對象的指針,按照bitwise的觀點,成員函數不能改變該指針,相當於在該成員函數內,指針是指針常量。然而,在const成員函數內,卻可以改變指針指向的對象。

但是,const成員函數的初衷,就是防止改變指針指向的對象。

PS:編譯器就是bitwise constness

2.logical constnessconst成員函數可以修改成員變量,但只有編譯器通過的情況下。

既然成員函數是const,對於編譯器而言,它就絕不能修改成員函數,如何讓它能通過編譯器檢查呢?在成員變量添加修飾符mutable,可以釋放掉成員變量的bitwise constness約束。也就是說,即使在const成員函數內,也可以修改mutable成員變量。


二、non-const版本調用const版本。

通常const版本的non-const的函數實現是一樣的,唯一的不同是返回類型。這時,我們可以在non-const版本調用const版本。

(*this)轉換爲const類型static_cast<const T>(*this)。這樣就才能調用const版本的函數

static_cast<const T&>(*this).function()

const版本的返回值(const T&)轉換成non-const

const_cast<T &>( static_cast<const T&>(*this).function())//(*this)返回的是reference of T

三、爲什麼non-const版本不能調用const版本

const成員函數絕對不會改變對象的邏輯狀態(logical state)non-const成員函數卻沒這條限制。如果const版本調用non-const版本,就會發生const函數內改變了對象的邏輯狀態,不管實際上有沒有改變,這完全取決於non-const版本


Tip04:確定對象被使用前初始化

一、賦值(assignment)和初始化(initialization)的區別

XXX::XXX(){
   Member1 = xxx;
   Member2 = xxx;
}

這叫賦值。而Java中不存在初始化列表,因此只能採用這種初始化方式,所以在Java的初始化對應的是C++的賦值


二、初始化的順序

類的成員變量總是以其聲明的方式被初始化。即類中聲明的順序是A,B,C,D…,那即使初始化列表的順序是B(xxx),D(xxx),C(xxx),A(xxx),實際初始化順序依然是A,B,C,D


三、什麼是non-local static對象。

一般聲明在函數內部的變量,稱之爲局部變量或者本地(local)變量。所以,non-local static對象,就是在函數體之外聲明的static對象


四、non-local static對象的初始化順序。

對於把不同的編譯單元內的non-local static對象的初始化順序根本,沒有明確定義。


五、如果其他類用到了non-local static對象,但不能確定該對象是否初始化,怎麼解決。

local static對象替換non-local static對象。C++保證,函數內的local static對象會在“該函數被調用期間”“首次遇到該對象之定義式”時被初始化。用函數調用(返回一個reference指向local static對象)替換non-local static對象,那麼該reference一定指向了一個歷經初始化的對象


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