《C++編程規範——101條規則、準則與最佳實務》(C++ Coding Standards——101 Rules, Guidelines and Best Practices)
名字空間與模組
第57條(D):將類型及其非成員函數介面置於同一名字空間中
第58條(D):應該將類型和函數分別置於不同的名字空間中,除非有意想讓他們一起工作
ADL(參數依賴尋找,也成Koeing尋找)。
關於57條和58條,在機器上實驗了一下,沒發現啥問題呀。???
第59條(A):不要在標頭檔中或者#include之前編寫名字空間using
名字空間 using 是為了使我們更方便,而不是讓我們用來叨擾別人的:在 #include 之前,絕對不要編寫 using 聲明或者 using 指令。
推論:在標頭檔中,不要編寫名字空間級的 using 指令或者 using 聲明,相反應該顯式地用名字空間限定所有的名字。(第二條規則是從第一條直接得出的,因為標頭檔無法知道以後其他標頭檔會出現什麼樣的 #include 。) 簡而言之:可以而且應該在實現檔案中的 #include 指令之後自由地使用名字空間級的 using 聲明和指令,而且會感覺良好。
第60條(D):要避免在不同的模組中分配和釋放記憶體
第61條(A):不要在標頭檔中定義具有連結的實體
// 不要在標頭檔中定義具有外部連結的實體int fudgeFactor;std::string hello("hi, lcz");void foo() { std::cout << "lcz" << std::endl; }
而解決方案也很簡單,應該像如下只在標頭檔中聲明:
extern int fudgeFactor;extern std::string hello;void foo(); // extern 對函數的聲明是可有可無的
在實現檔案中定義:
int fudgeFactor;std::string hello("hi, lcz");void foo() { std::cout << "lcz" << std::endl; }
同樣的,以下在標頭檔中定義名字空間級的static實體是更危險的行為(因為連結器通常不會報錯):
static int fudgeFactor;static std::string hello("hi, lcz");static void foo() { std::cout << "lcz" << std::endl; }
第62條:不要允許異常跨越模組邊界傳播
第63條(D):在模組的介面中使用具有良好可移植性的類型
錯誤處理與異常
第68條(B):廣泛地使用斷言記錄內部假設和不變式
斷言的強大怎麼高估都不算過分。1)按照資訊理論的原理,一個事件中所包含的資訊量與該事件發生的機率是成反比的。因此,如果assert觸發的可能性越低,它觸發時所提供的資訊量就越大。2)避免使用assert(false),應該使用assert( !"information message" ); // 這樣有一個很有用的好處,可以取代注釋。3)斷言是用來報告程式員的錯誤的,因此,不要使用斷言報告運行時的錯誤。
第69條:建立合理的錯誤處理策略,並嚴格遵守
第70條:區別錯誤與非錯誤
第71條:設計和編寫錯誤安全的程式碼
第72條:優先使用異常報告錯誤
第73條:通過值拋出,通過引用捕獲
第74條:正確地報告、處理和轉換錯誤
第75條:避免使用異常規範
錯誤處理與異常這一塊在項目中實踐得很膚淺,沒有什麼心得與體會。一般都是遇到錯誤了即返回,拋出錯誤記錄檔。
型別安全
第90條(C):避免使用類型分支,多使用多態
第91條(C):依賴類型,而非其表示方式
第92條(A):避免使用reinterpret_cast
如果需要在不相關的指標類型之間強制轉換,應該通過void進行轉換,不要直接使用reinterpret_cast.
例如:
T1 *p1 = ...T2 *p2 = reinterpret<T2*>(p1); // 糟糕!
應該寫成:
T1 *p1 = ....void *p = p1; // 先用void*指向p1指向的記憶體區T2 *p2 = static_cast<T2>(p);
第93條(A):避免對指標使用static_cast
第94條(A):避免強制轉換const(const_cast)
第95條(D):不要使用C風格的強制轉換
第96條(D):不要對非POD進行 memcpy 和 memcmp 操作
第97條(C):不要使用聯合(union)重新解釋表示方式
有兩種方式是可以接受的:1)讀取最後寫入的欄位(在一些介面需要統一參數而實際參數類型又不相同的時候,經常使用這一招);2)如果兩個POD是一union的成員,而且均以相同的欄位類型開始,那麼對這種匹配的欄位來說,寫入其中一個而讀取另一個是合法的。
第98條(A):不要使用可變長參數(...)
就算要用,我也不會編寫。呵呵
第99條(B):不要使用失效對象。不要使用不安全函數
不要使用不安全的C語言遺留函數:strcpy, strncpy, sprintf等C函數。
第100條(B):不要多態地處理數組
1)避免使用數組,而應該使用vector; 2)不要在數組或vector中儲存多態的值對象,而應該儲存物件指標(最好是智能指標)。