簡體   English   中英

函數如何在c ++中返回

[英]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);

為什么這不起作用?

函數調用

編譯器將執行以下操作之一:

  1. 將參數壓入堆棧並調用函數
    • 對於比您的功能更復雜的功能,通常會發生這種情況。
  2. 將參數加載到寄存器中並調用函數
    • 優化時可能會發生這種情況,並且有足夠的寄存器來保存需要傳遞的變量。
  3. 完全優化功能(內聯)
    • 對於像您這樣的微不足道的函數,明智的編譯器將使用最基本的優化級別來執行此操作,從而使您獲得與int a = 3相同的程序集。

C ++中的參考變量

在您的代碼中聲明為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;

是編譯器生成要(簡化)的代碼:

  1. 將常數3加載到寄存器
  2. 將寄存器加載到為

關鍵是:在任何一種情況下,都沒有為對象3分配長期的內存位置,因此,因此確實不能使int &a引用該對象。

“長壽命內存位置”是指將在分配操作之后繼續存在的位置。 存儲3的寄存器可能會在賦值操作后立即被覆蓋並重新使用,因此從理論上講,它甚至不符合int &a的目標(實際上, int &a僅可以引用存儲位置,而不能引用存儲位置。無論如何)。

  1. 這取決於調用約定。 使用cdecl (很常見),該函數將在EAX寄存器中返回x 然后它會被復制到分配到寄存器a

當然,優化的編譯器將優化整個過程以:

int x = 3;

2.您不能引用對象生命周期已結束的事物。 x的對象生存期在函數完成時結束。

任何合理的編譯器都可以(並且會)轉向

int a=f(3);

進入

int a=3;

該調用最初將編譯成類似將返回地址推入堆棧,然后傳遞參數的內容。 函數本身將編譯為彈出參數,彈出返回地址並再次推送參數,然后跳轉到返回地址。 一個簡單的優化器會檢測到沒有完成任何有用的工作,並把整個事情優化了。

  1. 當您調用函數f(3)時,調用語句的指令地址將保存在寄存器中,並且您的指令指針跳到函數f的第一條語句的地址。 功能f的新堆棧框架也被推入堆棧。 當函數調用返回時,將為從f(3)返回的int創建一個臨時變量,這是在執行int x=f(3);時將分配給x的內容int x=f(3); (因此,從f返回的值是在一個臨時文件中創建的,然后復制到x中),因此是的,正在為該返回值創建一個臨時文件。 為f(3)創建的堆棧也被破壞。

  2. 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM