2013-04-28 149 views
2

我已經在C++編程了幾個月了,當我經歷論壇時,我發現了一個趨勢。看來goto聲明通常被認爲是完全錯誤的使用,或者應該只在非常特定的情況下使用。什麼是goto陳述,使他們從根本上錯誤?爲什麼goto語句在C++中被視爲禁忌?

+3

您可能想從[這裏]開始(http://en.wikipedia.org/wiki/Considered_harmful) – 2013-04-28 18:28:39

+0

* goto *語句不是「根本錯誤」 - 優化的彙編代碼充滿了跳轉目的。但是* goto *使代碼難以被人讀取 - 對於一臺機器來說什麼是好的對於人來說通常不是那麼好。 – SChepurin 2013-04-28 18:48:14

+0

自20世紀60年代以來,Goto一直失寵。然而,一些着名作家,如Knuth,仍在使用它們。 – 2013-04-28 19:03:39

回答

7

最大的原因是它使代碼難以遵循。 goto並不是不好的;使用它編寫難以編寫的代碼很容易。

例如,您寧願閱讀哪一個?這:

int factorial(int n) { 
    int result; 

    if(n==0 || n==1) 
     result = 1; 
    else 
     result = n*factorial(n-1); 

    return result; 
} 

或者這樣:

int factorial(int n) { 
    int result; 

    if(n > 1) 
     goto big; 

    result = 1; 
    goto end; 

big: 
    result = n*factorial(n-1); 

end: 
    return result; 
} 

的兩種實現方式是一樣的機器,但首先是更清楚我們的人的眼睛。雖然有時候goto更清晰。例如,在C考慮這個(或C++沒有例外):

void process_big_file(FILE* foo) { 
    if(possible_failure_1(foo)) 
     goto cleanup; 

    // Do some work 

    if(possible_failure_2(foo)) 
     goto cleanup; 

    // Do some more work 

cleanup: 
    fclose(foo); 
} 

在這裏,用goto是有道理的,因爲它可以讓你把所有的清理代碼在一個地方,和goto 5事實上創建的邏輯流程執行。特別是在閱讀代碼時,很明顯,您總是(a)達到清理代碼,並且(b)總是達到清理代碼,這是重要的。在沒有例外情況下,我實際上認爲goto在嘗試組織(例如)清理代碼時是正確的。

+2

最後一個例子不應該在C++中使用。即使沒有例外,您也始終擁有與錯誤代碼/早期退貨一起工作的RAII。 – Pubby 2013-04-28 18:42:45

+0

作爲一項規則,我同意,但有時RAII不適合。在這種情況下,你需要一個好的舊指針(甚至不需要'auto_ptr',它會爲你實現RAII),然後你必須手動進行清理。一個很好的例子是帶有循環引用的對象圖,因爲RAII類型對象和'auto_ptr'都使用(a)對象生命週期或(b)引用計數(分別)來執行清理。當然,有時候你會插入傳統的C代碼,然後所有的地獄都會崩潰。 :) – sigpwned 2013-04-28 18:48:12

+0

@sigpwned最後一個例子是設計不佳的代碼的一個完美例子,其中一個函數做得太多。 – 2013-04-28 19:00:50

0

主要原因是goto使代碼的推理非常困難,如果不是不可能的話。 (請注意,對於隱藏的goto也是如此,就像使用break從循環中間退出一樣。)通常,如果您想要推理代碼的正確性,則需要輸入每個塊在頂部,並將其留在底部。如果沒有能夠推斷代碼的正確性,則無法確定它是否正確。

+0

關於我所看到的主題的最佳解釋。 – SChepurin 2013-04-29 05:28:43