C和C++引用傳遞和數組傳參引用

  • 2019 年 11 月 5 日
  • 筆記

引用傳遞有兩種傳參方式,具體可參考文章

概括地講,就是

  • *聲明一個形參是指針,所以需要傳遞指針實參,對應的函數實現也應當遵循指針的語法。這種實現思路並不針對於C或者C++,因為它們都有指針,所以都可以通過指針來達到引用傳參的效果,但是這種實現本質上不叫引用傳參,因為傳遞的是指針,而不是實參的引用。

  • &這個操作符,在形參聲明時,表示該形參是一個引用,不同於指針也不是取地址操作符,該引用操作符屬於C++的標準。函數被調用時,不會在內存中開闢新的空間,而是相當於給實參起了一個新名字,比如說如下代碼中:

    void fun(int &a){      a=2;  }  //調用fun函數  int num = 1;  fun(num);

    在這個代碼中,調用fun函數時,沒有給a形參開闢內存空間,a實際上就是num變量的別名,a和num屬於完全一樣的存在。

參考鏈接:

https://stackoverflow.com/questions/57483/what-are-the-differences-between-a-pointer-variable-and-a-reference-variable-in

https://stackoverflow.com/questions/2229498/passing-by-reference-in-c

理解了指針傳參和引用傳參,再講一下數組傳參。

先思考一下,下面這段代碼的輸出

#include<iostream>  using namespace std;  //通過數組名稱傳遞  void fun1(int arr[]);  //通過指針傳遞  void fun2(int *arr);  int main() {      int arr[2] = {2,0};      fun1(arr);      for(int i=0; i<2; i++) {          cout<<arr[i]<<endl;      }        cout<<endl<<endl;      fun2(arr);      for(int i=0; i<2; i++) {          cout<<arr[i]<<endl;      }    }    void fun1(int arr[]) {      arr[0]=9;      arr[1]=8;    }  void fun2(int *arr) {      arr[0]=7;      *(++arr)=6;  }

Output:

截圖_20191105023750.png

我們知道數組的本質就是一連串相同數據類型的數據,在內存中是連續存放的,同時數組的名稱,就是一個指針,它指向了第一個元素【下標為0】,所以,

fun1(int arr[])  fun2(int *arr)    

這兩種方式完全一樣,本質都是指針。既然如此,那麼就需要理解對指針的操作了。

//1.使用[]符號  /*  通過示例程序,可以發現,直接通過'指針[i]'操作,可以直接對相應的數組元素進行修改  */  arr[0]=9;  arr[1]=8;      //2.對指針進行算數運算  /*  arr的值實際上是一個內存地址,同一平台下指針大小都相同  比如PC x86上是4位元組,x64上是8位元組  但是,不同類型的指針步長不同,比如int類型的指針為4個位元組,char類型指針步長為1個位元組  所以下面這行代碼,如果arr是int類型指針,假設它的值為000000000062FE10,那麼++arr之後,它的值為000000000062FE14  如果arr是char類型指針,假設它的值為000000000062FE10,那麼++arr之後,它的值為000000000062FE11  */  ++arr;    //3.指針解引用  /*  通過'*'對指針進行解引用操作  */    //4.取出指針的地址'&'  /*  &是取址操作符,但是好像對指針取址也沒有什麼意義吧  */

聯想到這裡,再談一個容易出錯的誤區,先思考一下如下代碼的輸出:

//數組傳參求數組長度  #include<stdio.h>  int sizeofarr(int arr[]) {      printf("%dn",sizeof(arr));      printf("%dn",sizeof(arr[0]));      printf("%dn",sizeof(int));        return sizeof(arr)/sizeof(int);  }  int main() {      int arr[10] = {2,0,9,3,2,1,2,5,6,7};      printf("size of arr calculating by parameter: %d",sizeofarr(arr));        printf("nn%dn",sizeof(arr));      printf("%dn",sizeof(arr[0]));      printf("%dn",sizeof(int));        printf("the actual size of arr: %d",sizeof(arr)/sizeof(arr[0]));      return 0;  }

sizeof(arr)/sizeof(arr[0])這是一個十分常用的求數組長度的方法,前提是,不把arr傳遞到函數裏面求長度,為什麼這麼說呢?參考如下打印結果:

截圖_20191105031031.png

我的機子是64位的,所以sizeof(pointer)就是8,所以通過函數來求數組長度得到的結果就是2。

那麼如何避免這種錯誤呢?

要麼函數再加一個參數,表示數組的長度,要麼定義一個全局的常量表示數組的長度。

參考鏈接:https://stackoverflow.com/a/10349610