C++ 引用詳解

花了一天的時間來研究引用,引用在C語言裏是沒有的。它在C++中,是某對象的另外一個名字。主要用途是爲了描述函數的參數和返回值,特別是爲了運算符的重載。ios

廢話很少說,直接貼代碼函數

#include "stdafx.h"
#include <iostream>

int& r_fun_r(int& param)
{
    int result = param++;
    return result;
}
int fun_r(int& param)
{
    int result = param++;
    return result;
}
int& r_fun(int param)
{
    int result = param++;
    return result;
}
int fun(int param)
{
    int result = param++;
    return result;
}

int main()
{
    using namespace std;
    int param_in_main = 1; 

    
    int result = r_fun_r(param_in_main);
    cout << result << param_in_main << endl;
    result = r_fun(param_in_main);
    cout << result << param_in_main << endl;
    result = fun_r(param_in_main);
    cout << result << param_in_main << endl;
    result = fun(param_in_main);
    cout << result << param_in_main << endl;
    getchar();
    return 0;
}

以上定義了四個函數,分別對應有無傳遞引用參數,有無返回引用值。性能

編譯,返回引用值的函數r_fun_r(),r_fun()發出了警告:spa

警告 C4172 返回局部變量或臨時變量的地址。指針

說明了2個問題:一,返回值爲一個地址(或者說是個隱藏的指針)。二,即便在函數內部返回的是一個int型變量,編譯器也會按照函數聲明返回一個地址。code

那麼,在main函數中,int result = r_fun_r(param_in_main);這句豈不是將一個地址賦給了一個int型變量?對象

繼續研究,進入反彙編。原來,blog

int result = r_fun_r(param_in_main);
 lea eax,[param_in_main] 
 push eax 
 call r_fun_r (011610B9h) 
 add esp,4

 mov ecx,dword ptr [eax] 

 mov dword ptr [result],ecx

函數確實返回了一個地址。編譯器講這個地址的內容取到ECX中,再複製到result變量所在的內存區域中。內存

但問題是,這個返回的地址所在的棧空間是r_fun_r()的棧。在call r_fun_r跳轉回以後,這個棧已經被釋放。此時再訪問棧中的數據會有很大的風險。get

因此函數返回的引用必需要在內存空間中已經分配好地址。

此外,若是使用引用做爲函數的傳入值和返回值,在函數壓棧的時候,壓入的是當前參數的地址,返回的也是一個地址。若是不用引用來傳入和返回,則壓棧時會複製一份參數的值來傳參。

這樣若是是大結構的傳入返回,就會增長代碼的負擔,性能下降!反彙編代碼以下:

int result = r_fun_r(param_in_main);
lea         eax,[param_in_main]  //[]傳入地址
push        eax 
call ...
。
。
。
result = r_fun(param_in_main);
mov         eax,dword ptr [param_in_main]  //傳入值!
push        eax  
call ...
。
。
。

 

關於引用在運算符重載中的使用。之後再看!!

相關文章
相關標籤/搜索