2010-08-04 44 views
19

我剛從草莓Perl獲得的Windows版g ++中發現了一些奇怪的行爲。它允許我省略返回聲明。在C++中省略return語句

我有一個返回一個包含兩個指針的結構的成員函數,稱爲boundTag

struct boundTag Box::getBound(int side) { 
    struct boundTag retBoundTag; 
    retBoundTag.box = this; 
    switch (side) 
    { 
     // set retBoundTag.bound based on value of "side" 
    } 
} 

這個功能給了我一些不好的輸出,我發現它沒有return語句。我本來打算返回retBoundTag,但忘了實際寫回報聲明。一旦我加入return retBoundTag;一切都很好。

但我已經測試過這個功能,並從中得到了正確的boundTag輸出。即使是現在,當我刪除return語句時,g ++也會在沒有警告的情況下編譯它。 WTF?它猜測返回retBoundTag

+5

您應該使用'-Wall'進行編譯。缺少返回語句被'-Wreturn-type'捕獲。 – jweyrich 2010-08-04 02:38:50

+0

我傾向於將關於缺少返回的警告轉換爲錯誤:'-Werror = return-type'。爲我節省了很多時間。 – 2016-07-12 17:08:51

回答

16

省略non-void函數中的return語句[main()除外],並在代碼中使用返回的值調用Undefined Behaviour

ISO C++ - 98 [6.6.3節/ 2]

帶表達式的return語句只能在返回值的函數被用來 ;表達式的值是 返回給函數的調用者。如果需要,表達式 將隱式轉換爲函數的返回類型,其中 將顯示在其中。退貨聲明可能涉及臨時對象 的構建和複製(class.temporary)。 流出 函數的末尾相當於沒有值的返回;這導致 未定義的行爲在值返回函數

例如

int func() 
{ 
    int a=10; 
    //do something with 'a' 
    //oops no return statement 
} 


int main() 
{ 
    int p=func(); 
    //using p is dangerous now 
    //return statement is optional here 
} 

通常克++給出warning: control reaches end of non-void function。嘗試編譯-Wall選項。

+7

省略return語句很好。執行到達函數的結尾而不會遇到返回語句會導致未定義的行爲。您可以在到達函數結束之前返回,或者通過拋出異常離開,或者根本不離開,並且所有都將被很好地定義。 – 2010-08-04 03:53:49

+0

爲什麼使用'p'有危險? – ajay 2013-10-18 20:42:33

+2

@ajay:這是因爲它不包含任何指定的值。 – 2013-10-19 07:23:06

12

C和C++不要求您擁有return語句。 可能沒有必要擁有一個,因爲該函數會進入無限循環,或者因爲它會引發異常。

Prasoon已經引用的標準的相關部分:

[6.6.3節/ 2]

帶表達式的return語句可在返回值的函數只使用;表達式的值返回給函數的調用者。如果需要,表達式將隱式轉換爲它所在函數的返回類型。返回聲明可能涉及臨時對象(class.temporary)的構建和複製。從函數的結尾流出相當於沒有值的返回;這會導致值返回函數中的未定義行爲。

這是什麼意思是沒有 return語句沒問題。但是到達函數的末尾而沒有返回是未定義的行爲

編譯器不能總是檢測到這些情況,所以不需要編譯錯誤(它必須解決暫停問題,以確定執行實際上是否到達函數的末尾)。這只是undefined如果發生這種情況應該發生什麼。它可能看起來有效(因爲調用函數只會查看返回值所在位置的垃圾值),它可能會崩潰,或使惡魔飛出你的鼻子。

+3

感謝您解釋爲什麼在非void中沒有顯式返回語句功能 :) – ajay 2013-10-19 11:25:21

2

即使aC++編譯不能總是檢測何時功能無法執行return語句,它通常可以

好的一面是,至少g ++使得使用命令行編譯器選項「-Wreturn-type」很容易檢測到這一點。你只需要記住啓用它。 (如果使用「-Wall」,它也會啓用。)