C語言中函數有兩種傳參的方式:傳值和傳址。 傳值方式,在函數調用過程當中會生成一份臨時變量用形參代替,最終把實參的值傳遞給新分配的臨時變量,即形參。它的優勢是避免了函數調用的反作用,卻沒法改變形參的值。若是要改變實參的值,只能經過地址傳參。安全
例如:傳值函數
void swap (int left, int right) { int temp = left; left = right; right = temp; } int main() { int a = 10; int b = 20; swap(a,b); return 0; }
例如:傳地址指針
void swap (int *_pleft , int * _pRight) { assert (NULL != _pleft && NULL != _pRight); int iTemp = * _pleft; *_pleft = * _pRight; *_pRight = iTemp; } int main() { int a = 10; int b = 20; swap(&a,&b); return 0; }
指針能夠解決問題,但不是很形象友好,不安全,所以C++中引入了一種新的符合類型-->引用。code
引用不是新定義一個變量,而是給已存在變量取了一個別名,編譯器不會爲引用變量開闢內存空間,它和它引用的變量共用同一塊內存空間。對象
void TestRef() { int iNum0 = 10; int &iNum1 = iNum0; iNum1 = 20; printf("&iNum0 = ",&iNum0); printf("&iNum1 = ",&iNum1); }
【引用特性】內存
void TestRef() { int iNum0 = 10; int &iNum1 = iNum0; int &iNum2 = iNum1; int &iNum3; // 定義引用時必須進行初始化 int &iNum6 = iNum0; int iNum7 = 20; &iNum6 = iNum7; // 引用一旦定義,就不可以在改變 }
【常引用】編譯器
void TestConstRef() { int iNum0 = 10; const int &iNum1 = iNum0; int &iNum2 = iNum0; const int &iNum2 = iNum1; const int &iNum3 = 20; float fNum4 = 10.0f; const int &iNum5 = fNum4; }
【函數形參】編譯
void swap(int &_iLeft, int &_iRight) { int iTemp = _iLeft; _iLeft = _iRight; _iRight = iTemp; }
【返回值】test
int Add(int _iLeft, int _iRight) { return _iLeft + _iRight; } int& Add(int & _iLeft, int& _iRight) { int iResult = _iLeft+_iRight; return iResult; }
注意:不要返回棧內存的引用變量
struct strTest { int a[100000]; }; void FunTest0(const strTest& test) {} void FunTest1() { int iBegin = GetTickCount(); strTest test; for (int iIdx = 0; iIdx < 10000; iIdx++) { FunTest0(test); } int iEnd = GetTickCount(); cout<<iEnd - iBegin<<endl; }
相同點:底層的實現方式相同,都是按照指針的方式來實現的。
不一樣點:
1.引用定義時必須初始化,指針能夠不用,正常狀況下需初始化爲NULL。
2.引用一旦定義就不能再改變其指向其餘的變量,但指針能夠。
3.能夠有多級指針,可是沒有多級引用。
一、引用在定義時必須初始化,指針沒有要求。
二、一旦一個引用被初始化爲指向一個對象,就不能再指向其餘對象,而指針能夠在任什麼時候候指向任何一個同類型對象。
三、沒有NULL引用,但有NULL指針。
四、在sizeof中含義不一樣:引用結果爲引用類型的大小,但指針始終是地址空間所佔字節個數。
五、引用自加改變變量的內容,指針自加改變了指針指向。
六、有多級指針,可是沒有多級引用。
七、指針須要手動尋址,引用經過編譯器實現尋址。
八、引用比指針使用起來相對更安全。