1. 程式人生 > >C和C++引用傳遞和陣列傳參引用

C和C++引用傳遞和陣列傳參引用

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

概括地講,就是

  • *宣告一個形參是指標,所以需要傳遞指標實參,對應的函式實現也應當遵循指標的語法。這種實現思路並不針對於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:

我們知道陣列的本質就是一連串相同資料型別的資料,在記憶體中是連續存放的,同時陣列的名稱,就是一個指標,它指向了第一個元素【下標為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("%d\n",sizeof(arr));
    printf("%d\n",sizeof(arr[0]));
    printf("%d\n",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("\n\n%d\n",sizeof(arr));
    printf("%d\n",sizeof(arr[0]));
    printf("%d\n",sizeof(int));
    
    printf("the actual size of arr: %d",sizeof(arr)/sizeof(arr[0]));
    return 0;
}

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

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

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

要麼函式再加一個引數,表示陣列的長度,要麼定義一個全域性的常量表示陣列的長度。

參考連結:https://stackoverflow.com/a/10349