C++函式傳值方式
阿新 • • 發佈:2018-12-16
本文主要分析C++裡面兩大類函式傳參方式:傳值和傳址(傳引用和傳指標)
1.傳值
我們知道當我們呼叫一個函式時,OS會在記憶體中為這個函式建立起一塊程式棧幀,這個棧幀提供了函式引數的儲存空間。
對於傳值這種方式,實際上是將函式引數進行了一次copy,傳遞到函式的實際上是變數的一個副本。在函式內部對引數進行的update不會影響到原本函式外的引數的值。
比如以下程式碼段:
#include <iostream>
using namespace std;
int add(int a, int added){
a = a + added* 10;
return a;
}
int main(){
int x = 10;
int added = 2;
cout << add(x, added) << endl;
cout << "x=" << x << endl;
return 0;
}
程式的輸出是:
30
x=10
由此可見add函式裡面對x更改,並不會影響到函式外的變數x。所以當我們call函式的時候,實際上是將第一個入參copy了一份,然後assignment給區域性變數a。
2.傳址
傳址在C++裡面有兩種:傳引用(&)和傳指標(*)。
2.1 Pass by Reference
reference扮演著外界與物件之間的一個間接手柄的角色。引用的宣告是在型別名稱和reference之間插入&符號。比如
int ival =1024;
int *pi = &ival;//代表指標變數
int & rval = ival;//代表引用變數。
上面的程式碼宣告的變數rval就是代表一個引用,間接指向變數ival。
有一點需要特備註意:C++規定reference代表的物件在初始化的時候指定了之後不允許再更改,必須從一而終。也就是說如果一個一個reference已經初始化過了,後面的assignment都是copy操作。
當我們通過reference的方式將物件傳遞給函式的時候,物件本身並不會做一次copy,而是對物件的地址做了一個複製。函式中對物件的任何操作都相當於是對傳入物件進行間接操作。
當我們使用pass by reference的時候,主要考慮兩點:
- 希望對函式傳遞引數進行修改
- 降低複製大型物件的額外負擔
現在對前面程式碼做一個很小的更改:
#include <iostream>
using namespace std;
int add(int &x, int added){
x = x + added*10;
return x;
}
int main(){
int x = 10;
int added = 2;
cout << add(x, added) << endl;
cout << "x=" << x << endl;
return 0;
}
···
這個時候的輸出是:
> 30
> x=30
所以當我們pass by reference,函式會更改入參物件資料。
## 2.2 Pass by Pointer
傳遞指標和傳遞reference的區別其實並不大,下面是傳遞pointer的使用方式:
```cpp
#include <iostream>
using namespace std;
int add(int *x, int added){
*x = *x + added*10;
return *x;
}
int main(){
int x = 10;
int added = 2;
cout << add(&x, added) << endl;
cout << "x=" << x << endl;
return 0;
}
輸出也是
30
x=30
2.3 the difference between passing a reference and a pointer
reference和pointer在使用上的功能幾乎相同,但是有一個很重要的區別在於:
- pointer指向的物件可能(也可能不是)某個實際物件,也就是pointer可能指向某個null。
- 當我們提領pointer的時候,一定要先確認非0 ,否則會導致不可確定的嚴重錯誤。
- reference則必定會代表某個物件,所以不需要做這種非零檢查。