[英]how does the function return in c++ work
我想知道如果我調用函數f(3),編譯器將如何保存該臨時int;
int f (int x) { return x; }
以及如何由編譯器執行:
int a=f(3);
就像做int a = x一樣嗎? (我知道x已經被銷毀了),或者它確實創建了一個稱為f(3)的臨時變量,例如int f(3)=x;
int& a=f(3);
為什么這不起作用?
編譯器將執行以下操作之一:
int a = 3
相同的程序集。 在您的代碼中聲明為int &a
的引用變量是“現有內存位置的另一個名稱”。 因此,聲明int &a
不會在任何地方為int
分配空間。 它只是聲明a
來引用已經分配的內存位置。
此位置可能是現有變量int b
,因此您可以說:
int b;
int &a = b;
在此, a
將指代與b
所指代的相同內容。 “現有對象的新名稱”是一個很好的習慣用法。
您可能會幻想說int &a = array[5]
,因此a
指向int
數組array
第6個元素,或者int &a = *(int*)0x12345678
指向特定的內存位置,但是我在偏離方向。
您的密碼
int &a = 3;
之所以無法工作,是因為3
是一個臨時對象,在執行該語句后會將該對象忘記。 為了從根本上理解問題,請考慮以下問題: 如果a
引用了已經分配的內存位置,則在執行int &a = 3
語句之后,它將不再引用臨時對象3
呢?
這也是函數中引用變量的常見問題:返回對函數局部對象的引用是未定義的行為...但是我又在離題。 你總是必須有一個“活,分配的對象”為a
指,故事的結尾。
像這樣的語句通常會發生什么
int a = 3;
是編譯器生成要(簡化)的代碼:
關鍵是:在任何一種情況下,都沒有為對象3
分配長期的內存位置,因此,因此確實不能使int &a
引用該對象。
“長壽命內存位置”是指將在分配操作之后繼續存在的位置。 存儲3的寄存器可能會在賦值操作后立即被覆蓋並重新使用,因此從理論上講,它甚至不符合int &a
的目標(實際上, int &a
僅可以引用存儲位置,而不能引用存儲位置。無論如何)。
cdecl
(很常見),該函數將在EAX寄存器中返回x
。 然后它會被復制到分配到寄存器a
。 當然,優化的編譯器將優化整個過程以:
int x = 3;
2.您不能引用對象生命周期已結束的事物。 x
的對象生存期在函數完成時結束。
任何合理的編譯器都可以(並且會)轉向
int a=f(3);
進入
int a=3;
該調用最初將編譯成類似將返回地址推入堆棧,然后傳遞參數的內容。 函數本身將編譯為彈出參數,彈出返回地址並再次推送參數,然后跳轉到返回地址。 一個簡單的優化器會檢測到沒有完成任何有用的工作,並把整個事情優化了。
當您調用函數f(3)時,調用語句的指令地址將保存在寄存器中,並且您的指令指針跳到函數f的第一條語句的地址。 功能f的新堆棧框架也被推入堆棧。 當函數調用返回時,將為從f(3)返回的int創建一個臨時變量,這是在執行int x=f(3);
時將分配給x的內容int x=f(3);
(因此,從f返回的值是在一個臨時文件中創建的,然后復制到x中),因此是的,正在為該返回值創建一個臨時文件。 為f(3)創建的堆棧也被破壞。
int& a=f(3);
不能作為參考。 引用是別名。 別名用於已經存在的東西。 f(3)返回要分配給變量的臨時副本。 由於在f(3)調用之后堆棧將消失,因此您無法真正在其上分配引用。
int& a=f(3);
-這樣做不好是要創建對臨時變量的引用。 在函數退出時,引用所引用的數據已清除,因此它現在是一個掛起的引用。
編譯器可能只處理int a = f(3);
如int a = 3;
在您概述的情況下,但是您永遠無法確定,因為最終這取決於特定的編譯器及其優化方式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.