2010-08-21 61 views
2

我讀過多重返回和多個goto語句都是糟糕的編程習慣。我有一個功能可以檢測到8種類型的錯誤。如果出現錯誤,我應該返回錯誤代碼還是應該使用goto statment來結束功能並從那裏返回。 無論何時在從函數返回之前都需要釋放內存,我認爲最好在函數結束時釋放內存(以便在函數結束時只釋放一個內存)多個返回語句與多個goto語句:哪一個更好?

但是,In我的功能,內存不分配。 在這種情況下,哪一個更好?多個回報或多個goto語句? 或者我們可以避免兩者?

編輯:一些避免兩種方法是,將參數傳遞給可以存儲errorType的函數。在進一步處理之前,可以在功能內檢查相同的東西。但是這也使代碼變得醜陋。

+0

這是一個主觀問題。你可以找到說各種事情的人,嚴格來說,他們都不是錯的。我說使用什麼適用於你和你正在閱讀代碼的任何其他人。無論你做出什麼樣的選擇,都要對它們保持一致。 – asveikau 2010-08-21 07:11:54

回答

3

如果你看一下轉到如何在C語言中使用,如Linux內核,它是用來做資源清理從函數返回之前。使用多個標籤以相反的採集順序釋放資源,其中較早的部分代碼跳轉到後來的goto標籤。

在C++中,您應該使用RAII來管理您的資源。然後你可以使用多個返回語句,任何需要的清理將自動發生。

但是,如果您檢測到許多不同類型的錯誤,則您的函數/方法可能表現較低,您可能需要考慮將函數/方法分解爲更小的單元。這可能會使錯誤處理變得更加困難,因爲現在可能有更復雜的返回路徑,所以爲了避免這種繁瑣的錯誤處理,請使用異常而不是錯誤返回值。這將與RAII很好地配合以自動清理資源。

6

我認爲多重返回語句很好,在處理內存分配和釋放時,使用智能指針等處理內存管理的東西幾乎總是值得的。

+0

對於多重返回語句沒有問題;我曾經看到程序員拒絕使用它,而是在if語句中使用5級或更多級別的縮進級別,這使得讀取比多次返回更難。 – stijn 2010-08-21 08:08:46

+0

程序有時很難調試,如果你有一個函數的多個返回 – pankajt 2010-08-21 08:21:55

+0

@DevilJin所以這個教條通常會去,但我從來沒有發現過這種情況。我認爲這是人們在實踐中被教導的很多事情中的一個,而這些事情完全是不真實的。 – EJP 2012-09-06 05:32:35

3

避免自己做內存管理。有可能你正在使用默認的分配器,新的會拋出異常。遵循RAII編寫C++代碼幷包裝所有分配資源的代碼。然後沒有必要手動釋放內存

1

我不會推薦goto,因爲你會被嚴重避免(即使我認爲goto是一個合理的方法有例外)。

多回報率很好。我傾向於保留這些用於守衛的條款。這是函數實現的第一部分由一個或多個if(x) return;語句組成的地方。這些嘗試識別不需要進行任何更多處理的錯誤參數或其他錯誤條件。

guard子句應該有助於將if-else嵌套保留爲其他代碼的最小值。我嘗試通過使用臨時結果來限制本節的一個返回。如果你仍然發現嵌套很深或者多個返回會有幫助,那麼這個函數可能會試圖做太多的事情,應該被重構成多個幫助函數。

+2

如果您正在編寫C代碼和/或不能使用異常,Goto實際上是*很棒*。不是拋出,而是轉入清理塊。有關正確使用goto的更多示例,請參閱Linux內核。 – asveikau 2010-08-21 07:18:01

+0

是的,那是我同意的一種轉變模式。 – 2010-08-21 07:22:59

2

任何方法/過程具有多個gotoreturn語句可以被轉化成具有出口中的一個點的一個(或更多)的其他方法,並沒有goto語句。

例如:

void proc1(...) { 
    // allocate thing 
    if (x) { 
     ... 
     // free thing 
     return; 
    } 
    ... 
    // free thing 
    return; 
} 

可以改寫爲:

void proc1(...) { 
    // allocate thing 
    proc1a(...); 
    // free thing 
} 

void proc1a(...) { 
    if (x) { 
     ... 
     return; 
    } 
    ... 
    return; 
} 

隨着思想的一點點,你可以同時避免爲每個return的重複的內存管理(IMO kludgy)goto解決方法。

你選擇的替代方案最終應該是由代碼的可讀性和可維護性,而不是由多條返回或gotos變糟的教條來激勵。

+0

+1是由於到期的原因。我經常使用gotos,但只能在類似C的代碼中使用。但即使對於C代碼,我也更願意將資源管理與業務邏輯分開。 – Dummy00001 2010-08-21 11:31:36

+0

在返回的情況下,編譯器已經爲你做了這個。因此,我不明白爲什麼程序員應該被教導自己去做,當結果是正式等價的時候,並且編譯器完成的轉換是100%機械和可靠的。 – EJP 2012-09-06 05:33:15

+0

@EJP - 理由是它(假定)使代碼更容易理解,如果有一個退出點。但是你也需要明白,「不存在多重收益」的教條(部分)是對20世紀60年代流行的「goto spaghetti」編碼風格的反應。 – 2012-09-06 07:19:34

0

您可以使用另一個參數作爲錯誤,就像您所說的那樣,或者甚至返回保留所有結果的結構。我曾經寫過一個BTree類,並使用struct方法返回search_results(我保留了如下內容:Did_I_find_it或者元素的位置以及其他一些事情的位置)。我更喜歡認爲這些參數用於輸入和返回語句功能的輸出。

後藤真的應該避免。這是最麻煩的解決方案。

0

NONE我想說

  • 也許你可能要split你的方法爲更小的方法

  • 人們有時用do{..}while(0)循環與break組合。這確保該方法僅從一個地方返回。除非您沒有看到任何其他選項,否則應避免使用goto

示例代碼:

int myMethod(){ 
    int retval = 0; 
    do{ 
     if(...){ 
     retval = 1; 
     break; 
     } 
     else if(...){ 
     retval = 2; 
     break; 
     } 
     else{ 
     retval = 3; 
     break; 
     } 
    }while(0); 
    return retval; 
} 
+0

''''''''''''''''''''LOL' – Timwi 2010-08-21 16:16:21

+0

它可以幫助您不會錯過關鍵組件。我'喜歡它:) – pankajt 2010-08-21 20:07:29

0

請注意,使用goto可能會禁用函數中的某些編譯器優化。因此,沒有很好的理由使用goto可能會導致效率較低的代碼。

此外,恕我直言,使用返回語句,而不是多個goto語句導致更可讀/可審查的代碼。有了goto,你必須搜索目標標籤,並確保nobobdy真正使用goto來模糊代碼。

而且,在C++中,您擁有強大的語言結構,例如異常和帶有析構函數的對象,這些析構函數在範圍退出時執行資源清理 - 因此,goto的使用非常有限。

1

在我看來,多重回報是好的,並不複雜。多條件檢查語句會降低性能並不必要地增加代碼長度。我總是習慣根據情況投入多個回報。據我所知,這不是一個糟糕的編程習慣。