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

Tip01C++爲一個語言聯邦

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


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


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


STL:一個template程序庫。this


編程守則:spa

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

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


2、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


3、#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

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

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

可是若是,成員變量是指向對象的指針,按照bitwise的觀點,成員函數不能改變該指針,至關於在該成員函數內,指針是指針常量。然而,在const成員函數內,卻能夠改變指針指向的對象。

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

PS:編譯器就是bitwise constness

2.logical constnessconst成員函數能夠修改爲員變量,但只有編譯器經過的狀況下。

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


2、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

3、爲何non-const版本不能調用const版本

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


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

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

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

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


2、初始化的順序

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


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

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


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

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


5、若是其餘類用到了non-local static對象,但不能肯定該對象是否初始化,怎麼解決。

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

相關文章
相關標籤/搜索