C++函數中參數的傳遞方式是傳值。在函數域中為參數重新分配內存,而把實參的數值傳遞到新分配的內存中。它的優點是有效避免函數的副作用(即改變實參的值)。 如果要求改變實參的值,怎么辦呢?如果實參是一個復雜的對象,重新分配內存會引起程序執行效率大大下降,怎么辦呢?在C++中有一種新的導出型數據類型—引用(reference)可以解決上面的難題。引用又稱別名(alias)。
1.用交換程序舉例說明 (1)直接通過傳值的方式無法更改實參的值
#include<iostream>using namespace std;void swap1(int x, int y){ int tmp = y; y = x; x = tmp;}void main(){ int a = 10; int b = 20; swap1(a,b);}a,b的值仍未交換,只交換了x,y的值。 (2)C語言中通過指針的方式可以交換
可以看到x,y與a,b的地址不同,額外為形參開辟了空間 (3)C++中提供引用的方式
可以看到x,y的地址與a,b相同,是a,b的別名,沒有重新分配空間。
2.總結 (1)傳引用可以直接更改實參的值 (2)傳引用不用額外分配空間保存實參的數值。 (3)不能定義空引用,即引用的對象必須存在。 3.引用的本質仍是指針 關于這一點,請參考博文 c++ 引用 底層實現機制
引用是在編譯的過程中被處理的,實際上就是在編譯層面對程序員進行的一個比較友好的語法,而在實現上是由編譯器完成了地址的傳遞,實質上還是指針。 不能簡單的理解為一個別名,我們可以這樣用,但是要知道底層就是一個指針變量,是要占用內存空間的,和define是不一樣的。1.變量的引用
int a = 10;int b = &a;b是a的引用
2.指針的引用
int a = 10;int *p = &a;int *&q = p;q是p的引用
3.數組的引用
int ar[10] = {0};int (&br)[10] = ar;br是ar的引用
4.常量的引用 (1)常量必須用常量引用
const int x = 100;const int &y = x;(2)變量可以用常量引用
int x = 100;const int &y = x;(3)不同類型間進行常引用
double x = 13.14;const int &y = x;可以看到y與x的地址不同,此時,不同類型之間進行賦值運算,一定會產生臨時對象(假設為tmp),最終y是tmp的引用。同時,應注意:對于所有的臨時對象,必須同樣假設它們是不可存取的,即具有常量的性質。當改變這種數據時,編譯器會指出錯誤,這是非常有用的提示,因為這個改變會導致信息丟失。
5.函數中的引用,即函數返回引用或函數參數中包含引用
(1)最經常看見引用的地方是在函數參數和返回值中。當引用被用作函數參數時,在函數內任何對引用的更改將對函數外的參數產生改變。 (2)當然可以傳遞一個指針來做相同的事情,但引用具有更清晰的語法。(可以把引用看作一個使語法更加便利的工具。) (3)如果函數返回一個引用,必須像從函數返回一個指針一樣對待。當函數返回時,無論引用關聯的是什么都應該存在,否則,將不知道指向哪一個內存
int* fun1(int *x) //(2){ (*x)++; return x; //正確,x指向確定的內存} int& fun2(int &x) //(1){ x++; return x; //正確,x指向確定的內存}int& fun3(){ int q; //return q; //錯誤,局部變量,最終指向不明確的內存 static int p; return p; //正確,盡管fun3運行結束,但是p被static修飾,為全局變量,生存作用域仍存在,指向明確的內存}int main(){ int a = 10; fun1(&a); //ugly(but explicit) fun2(a); //clean(but hidden) }當給函數傳遞參數時,人們習慣上通過常量引用來傳遞。雖然看起來似乎僅是出于效率考慮(通常在設計與裝配程序時并不考慮效率),但是這樣會帶來很多危險。拷貝構造函數需要通過傳值方式傳遞對象,但并不總是可行的 這種簡單習慣可以大大提高效率:傳值方式會調用構造函數和析構函數,但是如果不想改變參數,則可以通過常量引用傳遞,它僅需要將地址壓棧。
事實上,只有一種情況不適合用傳地址方式。就是當傳值是唯一安全的途徑,否則將會破壞對象時。所以需要依據上下文
新聞熱點
疑難解答