天天看點

【Effective C++筆記】讓自己習慣C++

以前看Effective C++的時候總感覺寫的很晦澀,裡面說到的條款好像沒太大作用,現在重新翻看瞬時覺得以前的想法不免幼稚可笑,不得不承認裡面還是有很多值得遵守的使用習慣,從另外一個角度來說它并不适合C++的初學者,更适合有一定C++使用經驗的開發者。當然書中說的有些東西體會的并不是特别深刻,但沒關系,可以先總結下來以後再重新檢視,把書讀薄。這個系列組織的方式會嚴格按照書裡面的章節來分,每章除了會摘錄書上的精華,會适當地加上一些自己的了解。這本書有一個很有意思的地方是以條款的形式來說明,看上去有點像法律法規之類的東西,我們經常會看到一些引用說來自這本書的條款XXX,有強迫症的同學可以把所有條款都背下來:-)

【條款01】視C++為一個語言聯邦

聯邦對應的英文單詞是federation,可以了解為一個大的集合。是的,C++就是一個大的語言特性的集合。嚴格來說,C++是個多重範式程式設計語言(面向過程、面向對象、函數式、泛型形式)。面向過程的代表是C語言,有人也說C++是C語言的一個超級,C++的設計基本上是以C語言為基礎的;面向對象的代表是Java,抽象、繼承、封裝、多态皆在C++中有所展現;函數式程式設計的代表是Haskell,還有現在比較火的Erlang,由于本人尚未在項目中使用過C++的函數式特性,是以不便發表意見,據說C++11包含了大量函數式特性,如lambda運算,有興趣的可以去實踐下;泛型程式設計應該是C++比較獨特的文法特性,大家用的比較多的STL中有大量的template實作。

C++高效程式設計守則視狀況而變化,取決于你使用C++的哪一部分。

【條款02】盡量以const,enum,inline替換#define

宏定義并不是一個很好的東西,你可以想象各種宏定義遍布的代碼,可讀性大打折扣。另外,使用不當也會造成很多麻煩,相信很多人都有過很多頭疼的經曆。

Meyers建議盡量用const、enum、inline來替換宏定義,對于單純常量,最好以const對象或enums替換#defines;對于形似函數的宏(macros),最好改用inline函數替換#defines。

【條款03】盡可能使用const

将某些東西聲明為const可幫助編譯器偵測出錯誤用法。const可被施加于任何作用域内的對象、函數參數、函數傳回類型、成員函數本體。

編譯器強制實施bitwise constness,但你編寫程式時應該使用“概念上的常量性”(conceptual constness)。

當const和non-const成員函數有着等值等價的實作時,令non-const版本調用const版本可避免代碼重複。

【條款04】确定對象被使用前已先被初始化

有句經典的詞是這麼說來着,resource acquisition is initialization(RAII),即資源擷取就是初始化,說的就是這個意思。

為内置對象進行手工初始化,因為C++不保證初始化它們。

構造函數最好使用成員初值列(member initialization list),而不要在構造函數本體内使用指派操作(assignment)。初值列列出的成員變量,其排列次序應該和它們在class中的聲明次序相同。

為免除“跨編譯單元之初始化次序”問題,請以local static對象(函數内的static對象)替換non-local static對象(該對象是global或是位于namespace作用域内,抑或在class内或file作用域内被聲明為static)。(singleton模式的一個常見實作手法)因為C++對“定義于不同的編譯單元的non-local static對象“的初始化相對次序并無明确定義。原因:決定它們的初始化次序相當困難,非常困難,根本無解。在其最常見形式,也就是多個編譯單元内的non-local static對象經由”模闆隐式具現化,implicit template instantiations“形成(而後者自己可能也是經由”模闆隐式具現化“形成),不但不可能決定正确的初始化次序,甚至往往不值得尋找”可決定正确次序“的特殊情況。

參考:Effective C++:改善程式與設計的55個具體做法(第三版) Scott Meyers著 侯捷譯

繼續閱讀