2017-10-28 44 views
2

考慮我們有一個由值返回一個函數:參考R值(R值的地址)

int func() { 
    int x = 10; // create local variable x with value of 5 
    return x; // create temporary copy of x which is returned, local variable x is destroyed 
} 

int main() 
{ 
    int y = func(); // temporary copy of x is copied to y, when it hits`;` the temporary object is destroyed 
    return 0; 
} 

糾正我,如果我錯了的東西我在評論說以上。

現在我們可以通過持續引用它來延長臨時對象的生命週期。

int main() 
{ 
    const int & y = func(); // now the temporary object (R-value) is not destroyed when it hits `;` thus the life time is lenghtened. 
    return 0; 
} 

的問題是:既然我創建了一個恆定的參考應該被銷燬臨時對象,難道就因爲引用只不過是「別名」 cout << &y << endl將打印的臨時對象的地址?還有那些存儲在內存中的臨時對象(R值)在哪裏(我使用原始類型int,但它可以是類)?

+3

臨時存儲的地方不是你可以知道的。這是實現定義。 –

+3

「存儲在內存中的那些臨時對象(R值)在哪裏?」爲什麼你甚至在意? – DimChtz

+0

@JesperJuhl那麼打印'cout <<&y << endl;'的地址不是那個臨時對象的地址嗎?那麼這個地址代表什麼? – kvway

回答

2

正如評論中所述,將const引用(或右值引用)指向臨時對象,將其生存期延長到該引用的那一個。

另外這些臨時對象(R值)存儲在內存中(我使用原始類型int,但它可以是類)?

這不是標準規定的。但是,您可以查看最常用的編譯器,瞭解他們將執行的操作。與海灣合作委員會開始了,沒有任何的優化,你會得到

func(): 
    push rbp 
    mov rbp, rsp 
    mov DWORD PTR [rbp-4], 10 
    mov eax, DWORD PTR [rbp-4] 
    pop rbp 
    ret 
main: 
    push rbp 
    mov rbp, rsp 
    sub rsp, 16 
    call func() 
    mov DWORD PTR [rbp-12], eax 
    lea rax, [rbp-12] 
    mov QWORD PTR [rbp-8], rax 
    mov eax, 0 
    leave 
    ret 

https://godbolt.org/g/8wPQqx

因此,返回值被壓入EAX寄存器裏面的功能,一旦返回,該值被壓入的堆棧幀main(),就像在主函數中創建了變量一樣。你會發現與其他編譯器類似的結果。當優化打開,好了,很明顯會發生:編譯器看到函數只是返回一些常數和完全elides出來:

func(): 
    mov eax, 10 
    ret 
.LC0: 
    .string "%i" 
main: 
    sub rsp, 24 
    mov edi, OFFSET FLAT:.LC0 
    xor eax, eax 
    lea rsi, [rsp+12] 
    mov DWORD PTR [rsp+12], 10 
    call printf 
    xor eax, eax 
    add rsp, 24 
    ret 

在這裏,我添加了一些printf()的調用將輸出的地址時髦的聖該計劃並非完全無足輕重。 所以它創建函數,但不會打擾它的調用,而只是再次將10寫入本地堆棧框架中的某個空間。如果你只是使用它的值,它將被放入一個寄存器,因爲不需要地址。