本週內,每天更新。
01.視C++爲一個語言聯邦
C++的特性主要來源四個大方面(四個次語言)
以C爲基礎
Object-oriented C++:面向類的思想,包括封裝、繼承、多態
Template C++:
模板類 STL
結論:
- C++高效編程守則視狀況而變化,取決於你用C++的哪部分
02.儘量以const,enum,inline替換#define
壞處
define不被視爲語言的一部分,在預編譯的時候可能就被對應數據和字符取代,編譯器看不到相關的記號
宏定義的函數存在非安全性
用const取代
定義常量指針:注意const的放置
class專屬常量:可以聲明的同時初始化;也可以在實現文件內初始化
用enum取代
無法取對應的地址(#define也得到,功能相似)
不想別人獲得pointer或reference指向該資源
用inline取代
- 某些時候,宏定義的函數不安全,可以用template inline的函數取代;因爲inline的函數也相當於內部直接插入一段代碼
結論:
對於單純常量,最好以const對象或enums替換#defines
對於形如函數的宏,最好改用inline函數替換
03.儘可能使用const
注意:
const出現在型號左邊,表示被指物是常量;在右邊表示指針自身是常量
STL的靜態指針: const std::vector::iterator 表示指針自身是常量,不能++;std::vector::const_iterator 表示被指物是常量
const成員函數
是爲了確認該成員函數可作用於const對象身上
真實程序中,const大多用於passed by pointer-to-const或passed by reference-to-const
bitwise constness(編譯器就是這種)和logical constness:
bitwise constness是成員函數只有在不更改對象的任何成員變量時就認爲是符合const,這個定義存在一定不足,因爲即使編譯器查不出更改也可能存在更改
logical constness是一個const成員可以修改它所處對象內的某些bits,但只有在客戶端偵測不出的情況下纔可以
通過mutable關鍵字,可以釋放掉non-static成員變量的bitwise constness約束,從而在const函數內也可以修改所在對象的mutable成員變量
在const和non-const成員函數中避免重複
- 實現常量性轉除。消除const的性質,具體的做法是在non-const的函數裏調用對應的const函數,並實現強制轉換(const_cast可以強制消除const屬性,static_cast可以實現強制轉換)
結論:
將某些東西聲明爲const可幫助編譯器真測出錯誤用法編譯器強制實施bitwise constness, 但編程應該使用“概念常量性”(具體問題具體分析,編譯器不可靠的意思)
當const和non-const成員函數存在等價實現,用non-const函數調用const版本可以避免代碼重複
04.確定對象被使用前已先初始化
手工初始化:
- 對於無任何成員的內置類型,需要手工初始化
構造函數最好使用成員初值列,而不要在構造函數內賦值操作。初值列列出的成語變量,其排列次序應該和它們在class中的聲明次序相同
要區分賦值和初始化,對於class的對象,在構造函數內賦值實際上是先調用了它們的默認構造函數,然後做賦值操作,比較低效
成員的初始化列表本質是調用複製構造函數,效率較高
規則:總是在初值列中列出所有成員變量,以免還需記住那些成員變量無需初值
爲了免除“跨編譯單元之初始化次序”的問題(就是定義文件之間的初始化沒有先後順序),應該以local static對象替換non-local static對象
non-local static:函數外的static對象就是non-local static變量
編譯單元:產出單一目標文件的源碼,基本上它是單一源碼文件加上其所含的頭文件
問題:C++對於不同編譯單元內的non-local static對象的初始化次序沒有明確定義
解決:用singleton的思想。將每個non-local static變量搬到專屬函數內,這些函數返回一個reference指向它所含的對象,然後用戶調用這些函數,不直接調用對象。這時,non-local static變成了local static
這種reference-returning函數的形式:定義並初始化一個local static, 然後返回它