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);输出的地址就不一样了,这一点我没有弄明白,还请各路大神解释一下。谢谢。
  欢迎拍砖

猜你喜欢

转载自blog.csdn.net/qq_18293213/article/details/78577239