C++傳參數的正確姿勢

vector傳遞參數

  前幾天寫一個很簡單的c++程序,但是中間遇到了很有趣的問題,搞得我當時一頓懵,後來弄懂了,簡單總結一下。
  話說到底是什麼問題呢?調用函數時,怎樣引入實參才能對實參本身改變內容,有時候你想當然的調用了函數func,func運行完,發現參數並沒有改變,這可如何是好?很簡單的一個問題,還請大神們不要嘲笑我這個大專生。
  咱們以對數組的元素加一爲例,首先數組以兩種方式來表示,第一個是vector,第二個就是普通的數組int a[] = {}這兩種方式。接下來看第一種方式:

1 形參是實參的引用

/**
 * 形參是對實參的引用, 所以形參怎麼變化, 實參就怎麼變化
 * 而且有返回值, 返回啥就是啥, 實參的內容改變了
 * 形參的內存地址和實參的內存地址是一樣的
 * */
vector<int> add(vector<int> &a){
    cout<<"引用數組的地址:"<<(void*)(&a)<<endl;
    for (int i=0; i<a.size();i++){
        a[i] += 1;
    }
    return a;
}

main函數如下:

int main(){
    vector<int> a(6, 0);
    a[0] = 9, a[1] = 8, a[2] = 7, a[3] = 6, a[4] = 4, a[5] = 3;
//    int a[] = {1, 2, 3, 4, 5, 6};
    vector<int> b = add(a);

    cout<<(void*)(&a)<<endl;
//    cout<<(void*)(&b)<<endl;

//    sortInters2(b);
    for (int num : a)
        cout<<num<<" ";
    cout<<endl;
    for (int num : b)
        cout<<num<<" ";
    return 0;
}

結果如下:
這裏寫圖片描述
首先看地址,原數組和引用數組的地址是一樣的,這其實十一句廢話,引用就是指向同一塊內存,對形參改變就是對內存中內容的改變,也就是對實參的改變,所以我的add函數還有必要有返回值嗎?沒必要了吧,

2 形參是實參的拷貝

/**
 * 形參是實參的拷貝, 也就是形參把實參拷貝進來, 在內存多了一份a
 * 而且有返回值, 返回的是拷貝的這一塊內存地址, 所以接收值內容改變了
 * 形參的內存地址和實參的內存地址不一樣
 * */
vector<int> add1(vector<int> a){
    cout<<(void*)(&a)<<endl;
    for (int i=0; i<a.size();i++){
        a[i] += 1;
    }
    return a;
}

main函數如下:

int main(){
    vector<int> a(6, 0);
    a[0] = 9, a[1] = 8, a[2] = 7, a[3] = 6, a[4] = 4, a[5] = 3;
//    int a[] = {1, 2, 3, 4, 5, 6};
    vector<int> b = add1(a);

    cout<<"  原數組的地址:"<<(void*)(&a)<<endl;
//    cout<<(void*)(&b)<<endl;

//    sortInters2(b);
    for (int num : a)
        cout<<num<<" ";
    cout<<endl;
    for (int num : b)
        cout<<num<<" ";
    return 0;
}

結果如下:
這裏寫圖片描述
可以看到引用數組和原數組的內存地址不一樣,而且原數組的數值沒有變化,add函數返回的值變了。實際上,引用數組是對原是數組進行了一次拷貝,也就是add函數操作的是拷貝的那一塊內存,而原始數組根本沒有變化,但是add函數有返回值,如果不看內存,我們還以爲add函數真的作用在了原始數組上。你覺着樣這個函數是不是很作啊,多拷貝出來一塊內存,也不想想內存有多貴?顯然這樣做有些多餘。接着看下面例子

3 形參是實參的引用

emmmm?上面不是有一個這樣的標題了,小編你糊塗了。莫慌莫慌,且看代碼

/**
 *  形參是實參的引用, 此時函數操作的是實參的內存地址, 雖然沒有返回值, 但是原來的內存對應的
 *  數值是改變了的.
 *  形參內存地址和實參內存地址一樣
 * */
void add3(vector<int> &a){
    cout<<"引用數組的地址:"<<(void*)(&a)<<endl;
    for (int i=0; i<a.size();i++){
        a[i] += 1;
    }
}

上面函數沒有返回值的!!!
main函數代碼如下:

int main(){
    vector<int> a(6, 0);
    a[0] = 9, a[1] = 8, a[2] = 7, a[3] = 6, a[4] = 4, a[5] = 3;
//    int a[] = {1, 2, 3, 4, 5, 6};

    cout<<"  原數組的地址:"<<(void*)(&a)<<endl;
    cout<<"調用函數前"<<endl;
    for (int num : a)
        cout<<num<<" ";
    cout<<endl;
    add3(a);

//    sortInters2(b);
    cout<<"調用函數後"<<endl;
    for (int num : a)
        cout<<num<<" ";
    cout<<endl;
    return 0;
}

結果如下:
這裏寫圖片描述
沒有返回值,形參的地址和實參的地址是一塊內存,所以操作形參就是對實參的操作,對吧,這才符合我們的要求,沒有多餘的內存,一個引用就解決了問題。這個是推薦的做法!!!

4 數組怎樣來操作

/**
 *  數組就相當於指針, 所以這個函數和上面那個函數是一致的
 * */
void add2(int a[]){
//    此處爲什麼用&a就不行了
    cout<<"引用數組的地址:"<<(void*)(a)<<endl;
    for (int i=0;i<6; i++){
        a[i] += 1;
    }
}

main函數代碼如下:

int main(){
//    vector<int> a(6, 0);
//    a[0] = 9, a[1] = 8, a[2] = 7, a[3] = 6, a[4] = 4, a[5] = 3;
    int a[] = {1, 2, 3, 4, 5, 6};
    cout<<"調用函數前"<<endl;
    for (int num : a)
        cout<<num<<" ";
    cout<<endl;
    cout<<"  原數組的地址:"<<(void*)(&a)<<endl;

    add2(a);

//    sortInters2(b);
    cout<<"調用函數後"<<endl;
    for (int num : a)
        cout<<num<<" ";
    cout<<endl;
    return 0;
}

結果如下所示:
這裏寫圖片描述
看到了吧,形參和實參的地址是一致的,add函數沒有返回值,但是內容改變了,所以這個情況和上面一個情況是一樣的,所以這也是推薦的做法。
  但是我有一個疑問,爲什麼我用
cout<<”引用數組的地址:”<<(void*)(&a);輸出的地址就不一樣了,這一點我沒有弄明白,還請各路大神解釋一下。謝謝。
  歡迎拍磚

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章