昨天,我發現自己編寫的代碼是這樣的:如果您不在C++中返回值,會發生什麼情況?
SomeStruct getSomeStruct()
{
SomeStruct input;
cin >> input.x;
cin >> input.y;
}
當然不忘回報其實我剛剛創建的結構體。奇怪的是,這個函數返回的結構中爲的值被初始化爲0(當使用g ++編譯時)。這只是一個巧合,還是另一個SomeStruct被隱式地創建並初始化了?
昨天,我發現自己編寫的代碼是這樣的:如果您不在C++中返回值,會發生什麼情況?
SomeStruct getSomeStruct()
{
SomeStruct input;
cin >> input.x;
cin >> input.y;
}
當然不忘回報其實我剛剛創建的結構體。奇怪的是,這個函數返回的結構中爲的值被初始化爲0(當使用g ++編譯時)。這只是一個巧合,還是另一個SomeStruct被隱式地創建並初始化了?
做了另一個SomeStruct獲得創建和隱式初始化的地方?
想想如何返回結構。如果x
和y
都是32位,那麼32位體系結構中的寄存器就太大了,64位體系結構中的64位值也是如此(@Denton Gentry的答案提到了簡單的值是多少返回),所以它必須分配到某個地方。使用這個堆是浪費的,所以它必須在堆棧上分配。但它不能在你的函數的棧幀上,因爲函數返回後它不再有效。
編譯器,而不是具有來電告訴調用的函數放在哪裏的結果(這可能是某處調用者的堆棧上),通過將調用的函數隱藏指針分配給它的空間。因此,它被設置爲零的位置在調用者上,而不是在您的getSomeStruct
函數上。
也有像「命名的價值迴歸優化」裏多餘的副本可以被省略優化。因此,如果您使用了缺少的return
,結果將直接在調用者分配的空間上創建,而不是創建臨時文件並將其複製。
要了解更多有關正在發生的事情,您必須查看調用者函數。它是初始化(爲零)一個「空」SomeStruct
,你稍後分配你的getSomeStruct
函數的返回值?還是在做別的事情?
對我來說,編譯器不允許它:http://codepad.org/KkzVCesh
脫落的一個聲明返回一個值(無明確返回值)函數的結束導致不確定的後果。對於gcc,您應該從開啓最有用的警告的-Wall
命令行開關開始。控制所需警告的具體gcc警告是-Wreturn-type
(包含在-Wall
中,我只是爲了完整性而提及)。
打開警告後,您還應該使用-Werror
將警告視爲錯誤,並使構建在檢測到錯誤的位置停止。
我一直很驚訝,這只是一個警告,而不是一個錯誤。它比它幫助更多地受到傷害。 – 2008-11-16 05:24:54
在C中不返回任何東西是合法的,它仍然沒有定義,但至少它是合法的。 – Jonathan 2008-11-16 06:55:18
對於大多數現代CPU架構的調用約定指定一個特定的寄存器來傳遞一個函數的返回值返回給調用者。調用者進行函數調用,然後使用指定的寄存器作爲返回值。如果你沒有明確地返回一個值,調用者將會使用該寄存器中的任何垃圾。
編譯器還將使用該函數內可用於內部計算的所有寄存器。指定用於保存返回值的寄存器也將用於該函數內的混雜計算。因此,當你忘記指定返回值時,找到正確的值奇蹟般地返回給調用者並不罕見:編譯器使用該寄存器來存儲對象。
不幸的是,即使在功能的瑣碎的變化會導致寄存器分配發生變化,因此,返回值將成爲真正的垃圾。
您沒有收到任何警告,因爲您沒有打開-Wall -Werror
。 (正如在其他答案中所述)
但是我認爲你可能得到了一個零填充的結果作爲結果,因爲堆棧對象是在調用函數中構造的默認值,可能帶有顯式的零參數,或者由於零上的零疊加麼?
我覺得這很有趣。隨着使用默認選項,下面的編譯器在編譯的GetSomeStruct()
功能時,以下行爲:
微軟VC,所有版本(因爲VC6反正):
error C4716: 'getSomeStruct' : must return a value
數字火星:
Warning 18: implied return of getSomeStruct at closing '}' does not return value
科莫:
warning: missing return statement at end of non-void function "getSomeStruct"
GCC:
沒有錯誤或鑑於以下幾個從標準(6.6句子的警告
。 3第2段):
沒有 表達式的return語句可用於僅在 函數不返回一個值, 即,與返回 型空隙的功能,構造(12.1),或一個 析構函數( 12.4)。 ...流失 函數的結尾等於 返回無值;這導致 處於未定義行爲的 值返回函數。
我會說在這種情況下編譯器不會給出錯誤的原因很少。爲什麼這麼多編譯器只給出警告或根本沒有診斷?
看起來它不允許它,因爲你的編譯器設置了警告被視爲錯誤。你認爲這可能是我的警告級別設置得太低的情況嗎? – 2008-11-16 04:41:58