C++傳引用和傳值,傳指標
我們需要傳資料而不改變資料儲存,直接傳值,如int a;
我們需要傳資料,並且改變值大小,需要傳地址,如 int * pa;
我們需要傳資料,並改變數結構中指標的指向,需要傳二級指標,如連結串列中的 node * * l;
...
以前是passl-by-value,而c++在c11中,引入了pass-by-reference,也就是傳引用。c++需要一個識別符號&。
給出下面程式碼
void my_swap(int* x, int* y) { *x = *x^*y; *y = *x^*y; *x = *x^*y; cout << "函式中引數x的地址 " << &x << endl; } void my_swap(int&a, int&b) { a = a^b; b = a^b; a = a^b; cout <<"函式中引數a的地址 "<< &a<< endl; } int main() { int www = 1; int a = 0; int b = 100; int x = 0; int y = 100; my_swap(&x, &y); my_swap(a, b); cout << a << " 主函式 a 的地址 "<<&a<<endl; cout << x << " 主函式x的地址 " <<&x<< endl; }
前者swap是傳值(生成拷貝,傳地址),而後者直接是傳引用,形參和實參的本質是一樣,引用只是一個別名。
執行結果如下
可以明顯看到,這2個過載函式中使用傳指標,所指向的地址是不同的,而使用傳引用,所指向的地址是相同的。
傳引用:被調函式對形參的任何操作都被處理成間接定址,即通過棧中存放的地址訪問主調函式中的實參變數。正因為如此,被調函式對形參做的任何操作都影響了主調函式中的實參變數。
傳值:被調函式的形式引數作為被調函式的區域性變數處理,即在棧中開闢了記憶體空間以存放由主調函式放進來的實參的值,從而成為了實參的一個副本。
int a=0; //定義a是一個int類變數 int& ra=a; //宣告ra是a的“引用”,變數ra具有變數a的地址 //引用不能在引用的基礎上再引用。
順便說一下,gcc在編譯時,O2級別優化,傳引用,和傳地址的彙編程式碼是一樣的。
在微軟的vc編譯器(vs2013)執行時,直接優化,傳引用,和傳地址的彙編程式碼是一樣的。
所以在我們寫程式碼時,傳引用,傳指標都可以,不過我自己也趨向於寫引用,在c++的模板中也大量使用引用,從制度上完善程式碼規範,能防微杜漸。
下面說一下,傳引用,和我們常說的“傳指標”之間的一些小區別。
A,傳引用需要初始化,指標不需要(但指標推薦每次都初始化,即使無值,也初始化為NULL)。
B,使用sizeof對其求大小不一樣,引用是對應資料的實際大小,而指標則依據機器固定為相應大小(32位為4位元組)。
C,指標更加靈活,++,--可以來訪問,而引用沒有這些。有多級指標,沒有多級引用。
D,引用相當於和被引用者“繫結”,而指標可以不斷改變。
...
從安全的角度,引用能替代指標,這個在很多高階語言,不論是解釋性語言還是編譯語言中都得到了體現。
但維持c++的靈活,我們依然可以使用指標,不過推薦使用引用。