2013-05-08 173 views
2

我讀here on SO如何:不返回值,從函數具有非void返回類型

在C++:

  1. 不從非void函數返回是未定義的行爲。
  2. ... analysis requires inspection of the entire program, which is incompatible with separate compilation, and which is not even possible in the general case ...

從我做了該網頁上的幾個答案,那是困難的,不可能逸岸有時,檢查return語句的功能的存在。這不是從非void函數返回的,而是由C++標準留下的未定義行爲。

但是,我聽說在Java中,同樣的事情在編譯時報告爲錯誤。

問:我的理解是否正確?而且Java如何實現相同?


編輯:只是要清楚,我感興趣的理解:

  1. 如果它是在與編譯器執行難C++標準沒有定義,怎麼就是Java能夠實現相同。

  2. 如果這樣做不難,那麼C++標準不應該將其定義爲錯誤嗎?如果存在從非void函數不return代碼路徑

+1

這不是很難分析這個刪除if。如果你不從非void函數返回,一個好的C++編譯器會很容易給你一個警告。 – 2013-05-08 13:16:57

回答

3

Java通過拒絕運行某些程序來實現它,即使它們總是返回一個值。看看下面的(愚蠢)方法

public boolean test() { 
    boolean var=true; 
    if(var) 
     return true; 
} 

的方法總是返回true,但Java仍然拒絕接受爲有效。 C++中的相同方法是合法的,因爲它總是返回一個值。

所以總結一下:如果編譯器不能證明它總會返回一個值,Java會拒絕你的方法。這有時會拒絕始終返回值的方法。

C++只要信任程序員總是返回一個值,然後在運行時炸掉,如果程序員未能返回一些東西。

+0

這是一個愚蠢的例子,當然不是任何事情的動機。在這種情況下,整個函數體將簡單地返回true;'。可能有更復雜的情況,但最常見的情況是'test()'調用一個不返回的函數。 – 2013-05-08 13:27:30

+0

當然,差異的真正動機是,即使知道它永遠不會被達到,在Java中提供return語句總是相當容易。具有值語義的用戶定義類型意味着這不是C++中的情況;有可能出現幾乎不可能提供退貨聲明的情況。 – 2013-05-08 13:31:10

+0

我遇到過現實世界中唯一遇到問題的情況是,在處理所有值的枚舉上進行切換時,所有情況都會返回。在這種情況下,你仍然需要一個默認值:或者一個新的返回值。 – MTilsted 2013-05-08 13:42:27

2

所有的C++編譯器,我知道的會報告錯誤或警告。

正如評論者指出的,反過來是而不是總是如此。編譯器可能會發出錯誤警告,因爲它無法正確「理解」代碼。

+2

而這些報道往往是錯誤的。 – 2013-05-08 13:18:17

+0

是的,這會但有時他們錯了。 – 2013-05-08 13:18:45

+0

@JamesKanze - 是的,編譯器檢查所​​有代碼路徑是否覆蓋所有情況並不容易。可能嗎?這是否類似於停機問題? – 2013-05-08 13:19:02

0

Java編譯器只需要遵循什麼Java Language Specification說:

(8.4.7)如果一個方法被聲明爲返回類型,則發生編譯時錯誤,如果該方法的主體可以正常完成(第14.1節)。

(14。1)但是,某些事件可能會阻止聲明正常完成:

1.中斷(第14.15節),繼續(第14.16節)和返回(第14.17節)語句導致可能阻止正常完成的控制權轉移包含它們的語句。

2.某些表達式的評估可能會拋出Java虛擬機的異常(第15.6節)。顯式拋出(§14.18)語句也會導致異常。異常導致可能阻止正常完成語句的控制權轉移。

......

更詳細地瞭解完整通常在JLS被定義,特別是§14。

2

Java可能會要求您編寫無法訪問的代碼。 考慮是這樣的:

void neverReturns() { throw SomeException(); } 
MyType function() { neverReturns();  } 

很明顯,你可以永不脫落的function(), 結束,但Java要求return語句反正。

但是,語言有一個很大的區別,其中 激發了C++不需要返回語句的事實。爪哇具有非常有限的一組價值對象(例如,intdouble),所有這些都具有容易構建的值(例如,00.0);一切都是一個指針(它將接受 null)。所以你總是有一些簡單的回報,在 的情況下,你知道這是不相關的。在C++中,用戶定義的 類型可以(通常是)具有值語義,並且很多時候, 不具有默認構造函數,或者可以輕鬆地構造 構造函數。假設必須提供 function()的返回語句,如果MyType 的唯一非拷貝構造函數需要兩個或三個參數,則所有類型都不具有值構造函數。如果所有Java需要 將是return null;

+0

也許這只是措辭,但你是否說C++沒有返回值的函數是可以的? – 2013-05-08 14:31:42

+0

@ShafikYaghmour當然。有一個未定義的行爲,如果你從一個應該返回一個值的函數的末尾落下。只要你沒有失敗,無論出於何種原因(例如,你調用了一個拋出異常的函數,或稱爲'exit'),那麼這沒有問題。我已經實現了僅有條件地支持某些函數的層次結構;不支持的功能只是拋出一個異常。 (這不是做這件事的最好方法,但我已經使用過了,而且我已經看到了它的使用。) – 2013-05-08 15:22:59

1

是的,你的理解是正確的。 java這樣做的方式是嚴格的,即使對於總是返回值的方法,也會發出錯誤。

假設您有以下方法。 我們知道它總會返回一個值,因爲所有的情況都被覆蓋:a要麼大於零,要麼小於或等於零。 但是java並不知道它看到一個帶有返回值的'if',一個'else if'帶有返回值但沒有'else',因此不會返回,因此會報告錯誤。

int foo(int a) { 
    if (a > 0) { 
    return -1; 
    } 
    else if (a <= 0) { 
    return 1; 
    } 
} 

修復代碼的Java需要從其他

int foo(int a) { 
    if (a > 0) { 
    return -1; 
    } 
    else /*if (a <= 0)*/ { 
    return 1; 
    } 
}