1. 程式人生 > >C++傳引用和傳值,傳指標

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++的靈活,我們依然可以使用指標,不過推薦使用引用。