2010-01-26 80 views
55

我一直在尋找一些例子下我的工作硬件接口++代碼,發現大致如下大量的報表:將常量放在if語句之後的原因是什麼?

if (NULL == pMsg) return rv; 

我敢肯定,我聽到人們說,把不斷首先是一個好主意,但爲什麼呢?是否這樣,如果你有一個大的聲明,你可以很快看到你在比較什麼或有更多的東西?

+4

+1一個非常好的問題標題。 – OregonGhost 2010-01-26 10:24:57

+1

很確定我已經看過這個問題不止一次,現在找不到它。 – 2010-01-26 10:30:52

+1

@ Idan:我很驚訝,我找不到它,但經過5分鐘的搜索後,我放棄了;-) – 2010-01-26 10:40:17

回答

76

因此,您不要將比較(==)與賦值(=)混合在一起。

正如你所知,你不能指定一個常量。如果你嘗試,compliler會給你一個錯誤。

基本上,它是防禦性編程技術之一。保護你自己。

+2

輝煌 - 非常感謝:-) – 2010-01-26 10:29:25

7

當常數是第一個時,如果意外地寫入=而不是==,編譯器會發出警告,因爲將值賦給常量是非法的。錯誤

if (pMsg = NULL) return rv; 

29

要寫作阻止你。然而,一個好的編譯器會提醒你這個問題,所以大多數人不會使用「恆定優先」的方式,因爲他們發現很難閱讀。

+0

在您的忍者編輯後+1。 – 2010-01-26 10:21:33

+8

+1提到現代編譯器無論如何都會提醒大家。另一個不使用C++的原因是爲了避免編寫錯誤的操作符重載的問題。 ('_bstr_t',哦,我多麼恨你。) – jamesdlin 2010-01-26 10:28:39

+0

+1提到可讀性/維護問題。 – Ben 2010-01-27 20:07:18

8

它停止single =賦值錯誤。

例如,

if (NULL = pMsg) return rv; 

將無法​​編譯,其中作爲

if (pMsg = NULL) return rv; 

將編譯並給你頭疼

2

他們說, 「防止賦值和比較的混合」。

在現實中,我認爲這是無稽之談:如果你是如此紀律,你不要忘了,在左邊放常數,你肯定不會混淆「=」「==」 , 你會? ;)

+0

不,但是,你有更多的機會避免出現錯誤多次擊鍵可能會導致鍵入不夠難以獲得第二個=。因此,你知道,錯字。 – 2010-01-26 10:33:39

+0

我只是好奇你有多少次這樣的錯字?打賭你沒有。 – 2010-01-26 10:36:33

+6

我想我認爲自己很有紀律,但無論你的編碼風格如何,每個人都會偶爾出現錯字,這種簡單的習慣可以避免像執行這樣的錯誤。在編譯時捕獲的錯誤在執行時值10 :-) – 2010-01-26 10:38:17

2

編譯器輸出警告很好,但我們現實世界中的一些人不能將警告視爲錯誤。顛倒變量和常量的順序意味着這個簡單的滑動總是顯示爲錯誤並且阻止編譯。你很快習慣了這種模式,它所保護的缺陷是微妙的,一旦引入就很難找到。

8

爲了澄清什麼,我在一些評論中寫道,這裏是有原因的 ++做這在C代碼。

有人寫,說,串類,並決定轉換運算符添加到const char*

class BadString 
{ 
public: 
    BadString(const char* s) : mStr(s) { } 

    operator const char*() const { return mStr.c_str(); } 

    bool operator==(const BadString& s) { return mStr == s.mStr; } 

    // Other stuff... 

private: 
    std::string mStr; 
}; 

現在有人盲目地應用constant == variable「防禦性」的編程模式:

BadString s("foo"); 

if ("foo" == s) // Oops. This compares pointers and is never true. 
{ 
    // ... 
} 

這是國際海事組織,這是一個比意外分配更爲陰險的問題,因爲你無法從呼叫站點得知任何明顯錯誤的事情。

當然,真正的教訓是:

  1. 不要寫你自己的字符串類。
  2. 避免隱式轉換操作符,特別是在執行(1)時。

但有時你正在處理你無法控制的第三方API。例如,Windows COM編程中常見的_bstr_t字符串類遭受此缺陷。

+0

我見過很多禁止運算符重載的地方。 Yay C++。 – 2010-01-26 20:54:42

+0

不會s ==「富」有相同的問題,雖然? – 2010-01-31 19:21:42

+0

@Jon Cage:不是。不直覺地,雖然''foo「== s'不會觸發期望的歧義錯誤,但是's == ==」foo「'。 (作者可能會實現'bool MyString :: operator ==(const char *)const',它將解決's == =='foo''歧義,但仍然無法修復'foo'== s'。) – jamesdlin 2010-01-31 20:51:55

0

我忘記了文章,但報價又是這樣的:「很顯然它更容易記住把恆定的第一,比它是要記住使用==」;))