1. 程式人生 > >值傳遞,引用傳遞

值傳遞,引用傳遞

1:指標傳遞

指標傳遞引數本質上是值傳遞的方式,它所傳遞的是一個地址值。值傳遞過程中,被調函式的形式引數作為被調函式的區域性變數處理,即在棧中開闢了記憶體空間以存放由主調函式放進來的實參的值,從而成為了實參的一個副本。值傳遞的特點是被調函式對形式引數的任何操作都是作為區域性變數進行,不會影響主調函式的實參變數的值。(這裡是在說實參指標本身的地址值不會變,但是如果對這個地址所指向的資料進行修改,那麼實際上就會反應到全域性變數中)

2:引用傳遞

而在引用傳遞過程中,被調函式的形式引數雖然也作為區域性變數在棧中開闢了記憶體空間,但是這時存放的是由主調函式放進來的實參變數的地址(int &a的形式)。被調函式對形參的任何操作都被處理成間接定址,即通過棧中存放的地址訪問主調函式中的實參變數。正因為如此,被調函式對形參做的任何操作都影響了主調函式中的實參變數。

引用傳遞和指標傳遞是不同的,雖然它們都是在被調函式棧空間上的一個區域性變數,但是任何對於引用引數的處理都會通過一個間接定址的方式操作到主調函式中的相關變數。而對於指標傳遞的引數,如果改變被調函式中的指標地址,它將影響不到主調函式的相關變數。如果想通過指標引數傳遞來改變主調函式中的相關變數,那就得使用指向指標的指標,或者指標引用。

為了進一步加深大家對指標和引用的區別,下面我從編譯的角度來闡述它們之間的區別:

程式在編譯時分別將指標和引用新增到符號表上,符號表上記錄的是變數名及變數所對應地址。指標變數在符號表上對應的地址值為指標變數的地址值,而引用在符號表上對應的地址值為引用物件的地址值。符號表生成後就不會再改,因此指標可以改變其指向的物件(指標變數中的值可以改),而引用物件則不能修改。

3:

無論你傳值還是傳指標,函式都會生成一個臨時變數,

但傳引用時,不會生成臨時變數,

當你傳值時,只可以引用值而不可以改變值,但傳值引用時,可以改變值,

當你傳指標時,只可以改變指標所指的內容,不可以改變指標本身,但傳指標引用時,既可以改變指標所指的內容,又可以改變指標本身,

但傳引用主要是它不生成臨時變數,不進行返回值copy等,速度快

4:例項point.cpp

#include <iostream>

using namespace std;

void func1(int a) {
	a ++;
}

void func2(int &a) {
	a ++;
}

void func3(int *a) {
	cout<<"func3:"<<a<<endl;
	*a = *a + 1;
}


class A{
private:
	int a;
public:
	A(int a) {this->a = a;}
	int get_a() {
		return a;
	}
};

void func4(A &a) {
	cout<<a.get_a()<<endl;
}

int main() {

	int a = 2;
	func1(a);
	cout<<a<<endl;
	func2(a);
	cout<<a<<endl;
	int *b;
	b = &a;
	cout<<b<<endl;
	func3(b);
	cout<<b<<endl;
	cout<<a<<endl;
	cout<<*b<<endl;
	cout<<"-----"<<endl;

	func2(*b);
	cout<<*b<<endl;

	cout<<"-----"<<endl;
	A *aa = new A(4);
	func4(*aa);	
}