1. 程式人生 > >C++引用做函式引數和函式的返回值是引用的幾種情況

C++引用做函式引數和函式的返回值是引用的幾種情況

引用做函式引數

引用的內部實現,是常指標,所以引用其實是對指標做了一些限制,這種限制的意義是在某些應用場景中,使用引用具有更好的 實用性和可讀性。具體講,引用最常見的用處是在做函式引數的時候,對比指標做函式引數,比如:

指標做函式引數:

void myswap(int *a,int *b)
{
	int tmp=*a;
	*a=*b;
	*b=tmp;
}

引用做函式引數:

void myswap(int &a,int &b)
{
	int tmp=a;
	a=b;
	b=tmp;
}

從可讀性上講,指標需要 * 去改變記憶體空間的值,呼叫的時候實參需要取地址,而引用,這些工作編譯器幫我們完成了。另外,指標做函式引數,如果不小心修改了形參的值,那麼之後的操作就不是修改我們本來想修改的實參的值,比如:

void swap_(int *a,int *b)
{
	int tmp=*a,n=16;
	a=&n;//意外地
	*a=*b;
	*b=tmp;
}

所以為了避免這種意外,函式需要設計成下面的樣子

void myswap(int * const a,int * const b);

這就是引用的本質,所以在c++中設計的引用是有實際需求的。C是在應用中逐步堆積起來的,而C++是專門針對應用需求設計出來的。

函式的返回值是引用

int getDouble(int a)
{
	int tmp=a*2;
	return tmp;
}

上面的函式裡,返回的是一個臨時變數的值,在函式呼叫結束的時候,會儲存一份這個值的副本,把副本拷貝給主調函式,所以是沒有問題的,但是主調函式如果是 int &n=getDouble(n),這樣編譯會報錯,因為返回的只是一個值,是沒有地址的。

/*******************************************************************************************************************************/

int& getDouble(int a)
{
      int tmp=a*2;
      return tmp;
}

上面函式返回了臨時變數的一個引用,引用是這個變數的別名,此時就有兩種情況 一種是用變數去接返回值,如下:

int a=10;
a=getDouble(a);

此時,a是有地址的,只是用返回值的一個副本去給變數a賦值,沒有問題,而如果像下面的程式碼,用變數的引用去接返回值:

int a=10;
int &b=getDouble(a);

因為引用是一個地址的別名,而這個地址是臨時的,在函式呼叫結束返回後,這個地址就被析構掉了。

如果返回的是靜態或者全域性的變數的引用,如下:

int& getTimes()    
{    
    static int t=0;    
    t++;    
    return t;    
} 

仍舊是用引用去接返回值,因為變數t的地址不是臨時的棧區,所以函式呼叫結束時地址不會析構。

綜上,使用指標一定要找到記憶體,沒有記憶體,指標的存在是沒有意義的,而引用是常量指標,所以使用引用也必須要找到記憶體地址,看記憶體是在哪個區分配的,何時產生,何時被析構掉,指向一個被析構掉的隨機的地址的指標是沒有意義的,繫結在一個被析構掉的隨機的地址的引用也是沒有意義的。