本節書摘來自異步社群出版社《c++程式設計規範:101條規則、準則與最佳實踐》一書中的第1章,第1.2節,作者:【加】herb sutter , 【羅】andrei,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。
摘要
高度重視警告:使用編譯器的最高警告級别。應該要求建構是幹淨利落的(沒有警告)。了解所有的警告。通過修改代碼而不是降低警告級别來排除警告。
讨論
編譯器是你的朋友。如果它對某個構造發出警告,一般表明代碼中存有潛在的問題。
成功的建構應該是無聲無息的(沒有警告的)。如果不是這樣,你很快就會養成不仔細檢視輸出的習慣,進而漏過真正的問題(見第2條)。
排除警告的正确做法是:(1)把它弄清楚;然後,(2)改寫代碼以排除警告,并使代碼閱讀者和編譯器都能更加清楚,代碼是按編寫者的意圖執行的。
即使程式一開始似乎能夠正确運作,也還是要這樣做。即使你能夠肯定警告是良性的,仍然要這樣做。因為良性警告的後面可能隐藏着未來指向真正危險的警告。
示例
例1 第三方頭檔案。無法修改的庫頭檔案可能包含引起警告(可能是良性的)的構造。如果這樣,可以用自己的包含原頭檔案的版本将此檔案包裝起來,并有選擇地為該作用域關閉煩人的警告,然後在整個項目的其他地方包含此包裝檔案。例如(請注意,各種編譯器的警告控制文法并不一樣):
// ……在一個使用者定義的allocator中未使用hint ……
// 警告:unused parameter 'localityhint
pointer allocate( size_type numobjects, const void *localityhint = 0 ) {
return static_cast( mallocshared( numobjects * sizeof(t) ) );
}
// 消除了警告的新版本
pointer allocate( size_type numobjects, const void / localityhint */ = 0 ) {
return static_cast( mallocshared( numobjects * sizeof(t) ) );
}<code>`</code>
例3 “定義了從未使用過的變量”(variable defined but never used)。檢查一下,确認并不是真正要引用該變量。(raii基于棧的對象經常會引起此警告的誤報,見第13條。)如果确實不需要,經常可以通過插入一個變量本身的求值表達式,使編譯器不再報警。(這種求值不會影響運作時的速度。)
// 警告:missing "return"
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 “有符号數/無符号數不比對”(signed/unsigned mismatch)。通常沒有必要對符号不同的整數進行比較和指派。應該改變所操作的變量的類型,進而使類型比對。最壞的情況下,要插入一個顯式的強制轉換。(其實不管怎麼樣,編譯器都将為你插入一個強制轉換,同時還會發出警告,是以還不如顯式地先發而制之。)
例外情況
有時候,編譯器可能會發出煩人的甚至虛假的警告(即純屬噪聲的警告),但是又沒有提供消除的方法,這時忙于修改代碼解決這個警告可能是勞而無功或者事倍功半的。如果遇到了這種罕見的情形,作為團隊決定,應該避免對純粹無益的警告再做無用功:單獨禁用這個警告,但是要盡可能在局部禁用,并且編寫一個清晰的注釋,說明為什麼必須禁用。
參考文獻
[meyers97] §48[8] ● [stroustrup94] §2.6.2