1. 程式人生 > >C++函式傳值方式

C++函式傳值方式

本文主要分析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則必定會代表某個物件,所以不需要做這種非零檢查。