天天看點

Effecvtive C++筆記:讓自己習慣C++

C++的四個語言層次:

C:C++是以C為基礎的。基本資料類型、語句、預處理器、數組、指針等統統來自C。

Oject-Oriented

C++:面向對象這一特性包含了:類,封裝,繼承,多态,虛函數等

Template

C++:C++的泛型程式設計能力。

STL:一個标準的template庫,裡面介紹了容器、疊代器、算法以及函數對象等模闆類和模闆函數。

綜述:C++并不是一個帶有一組守則的一體語言:它是從四個次語言組成的聯綁政府,每個次語言都有自己的規約。

對于單純常量,最好以const對象或enums替換#define。

對于形似函數的宏,最好改用inline函數替換#define

STL的疊代器是以指針為根據塑模出來,是以疊代器的作用就像個T*的指針。聲明疊代器為const就像聲明指針為const一樣(即聲明一個T*const指針),表示這個疊代器不得指向不同的東西,但它所指的東西的值是可以改動的。如果希望疊代器所指的東西是不可被改動的,需要的是const_iterator。

請記住

将某些東西聲明為const可幫助編譯器偵測出錯誤用法。const可被施加于任何作用哉内的對象、函數參數、函數傳回類型、成員函數本體。 編譯器強制實施bitwise constness,但你編寫程式時應該使用“概念上的常量性”。 當const和non-const成員函數有着實質等價的實作時,令non-const版本調用const版本可以避免代碼重複。

類的構造函數的次序是先執行構造函數初始化清單,初始化所有成員變量,然後再執行構造函數體,構造函數體内的成員指派已經不屬于初始化的範疇,成員都是用拷貝指派。

如果類沒有初始化清單,則類會先執行預設構造函數,構造出所有成員變量後,再執行函數體内的拷貝指派。

C++類的成員初始化是有着明顯的次序的,一般是基類的成員先初始化,然後派生類的成員按定義的順序初始化。是以類的構造函數初始化清單上的初始化順序跟類真實的成員初始化順序是沒有關系的。

“不同編譯單元内定義之non-local static對象”

static對象,其壽命從被構造出來直到程式結束為止。

函數内的static對象稱為local static對象(因為它們對函數而言是local),其他static對象稱為non-local

static對象。程式結束時static對象會被自動銷毀,也就是它們的析構函數會在main()結束時被自動調用。

當我們的某個編譯單元内的某個non-local static對象的初始化動作使用了另一編譯單元的某個non-local

static對象,它所用到的這個對象可以尚未被初始化。C++關于定義于不同編譯單元内的non-local static對象的初始化次序并無明确定義。

比如在a.cpp裡我們定義一個類,一個該類的對象

現在同一個項目下的b.cpp檔案中有一個類,類構造函數用到了tfs對象。

現在如果我們建立了一個Directory對象

上面的代碼就可能會出問題,除非能保證tfs在tempDir之前先初始化,否則tempDir的構造函數會用到尚未初始化的tfs。

解決方案:

C++保證,函數内的local static對象會在該函數被調用期間,首次遇到該對象的定義的時候被初始化。

是以如我們把tfs和tempDir設計為一個函數,函數傳回該類的一個static對象引用就可以解決問題了。

是以我們可以改寫上面的代碼:

為内置型對象進行手工初始化,因為C++不保證初始化它們。 構造函數最好使用成員初始化清單,而不要在函數體内使用指派操作。初始清單列出的成員變量,其排列次序應該和它們在class中的聲明次序相同。 為免除“跨編譯單元之初始化次序”問題,請以local static對象替換non-local static對象。