95
王者榮耀
C++編程規範之1:在高警告級別幹淨利落地進行編譯
原則:
高度重視警告:使用編譯器的最高警告級別。應該要求構建是幹淨利落的(沒有警告)。理解所有的警告。通過修改代碼而不是降低警告級別來排除警告。
解釋:
編譯器是你的朋友。如果它對某個構造發出警告,一般表明代碼中存有潛在的問題。
成功的構建應該是無聲無息的(沒有警告的)。如果不是這樣,你很快就會養成不仔細查看輸出的習慣,從而漏過真正的問題。
排除警告的正確做法是:(1)把它弄清楚;(2)改寫代碼以排除警告,並使代碼閱讀者和編譯器都能更加清楚,代碼是按編寫者的意圖執行的。
即使程序一開始似乎能夠正確運行,也還是要這樣做。即使你能夠肯定警告是良性的,仍然要這樣做。因為良性警告的後麵可能隱藏著未來指向真正危險的警告。
示例:
1. 第三方頭文件。
無法修改庫頭文件可能包含引起警告(可能是良性的)的構造。如果這樣,可以用自己的包含頭文件的版本將次文件包裝起來,並有選擇的為該作用域關閉煩人的警告,然後在真個項目的其他地方包含此包裝文件。
2. 未使用函數參數。
檢查一下,確認確實不需要使用該函數參數(比如,這可能是一個為了未來擴展而設的占位符,或者是代碼沒有使用的標準化函數簽名中的一個必需部分)。如果確實不需要,那直接刪除函數參數名就行了。
//。。。。在一個用戶定義的allocator中未使用hint。。。。。 //警告:unused parameter 'localityHint' pointer allocate(size_type numObjects,const void *localityHint = 0) { return static_case<pointer>(mallocShared(numObjects *sizeof(T))); } //消除了警告的新版本 pointer allocate(size_type numObjects,const void * /*localityHint*/ = 0) { return static_case<pointer>(mallocShared(numObjects *sizeof(T))); }
3. 定義了從未使用的變量
檢查一下,確認並不是真正要引用該變量。如果確實不需要,經常可以通過插入一個本身的求職表達式,使編譯器不再報警。
//警告:variable 'lock' is defined but never used void Fun() { Lock lock; //...... } //可能消除了警告的新版本 void Fun() { Lock lock; lock;//這一句是關鍵 //...... }
4. 變量使用前可能未經初始化
需要初始化變量
5. 遺漏了return語句
有時候編譯器會要求每個分支都有return語句,即使控製流可能永遠也不會到達函數的結尾。這可能是一件好事,因為有時候你僅僅是認為控製不會運行到結尾。例如,沒有default情況的switch語句不太適應變化,應該加上執行assert(false) 的default情況。
//警告:missing "return" int Fun(color c) { switch(c) { case Red: return 2; case Green: return 0; case Blue: case Black: return 1; } } //消除了警告的版本 int Fun(color c) { switch(c) { case Red: return 2; case Green: return 0; case Blue: case Black: return 1; default: assert(!"should never get here!")//!"string"的求值結果為false return -1; } }
6. 有符號/無符號數不匹配
通常沒有必要對符號不同的整數進行比較和賦值。應該改變所操作的變量的類型,從而使類型匹配。最壞的情況下,要插入一個顯示的強製轉換。
7.有時候編譯器可能會發出煩人的甚至虛假的警告(即純屬噪聲的警告),但是又沒有提供消除的方法,這時忙於修改代碼解決這個警告可能是勞而無功或者事倍功半的。如果遇到了這種罕見的情形,作為團隊決定,應該避免對純粹無益的警告再做無用功:單獨禁用這個警告,但是要盡可能在局部禁用,並且編寫一個清晰的注釋,說明為什麼必須禁用。
最後更新:2017-04-03 14:54:29