天天看點

《C++程式設計規範:101條規則、準則與最佳實踐》——1.2:在高警告級别幹淨利落地進行編譯

本節書摘來自異步社群出版社《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

繼續閱讀