C/C++中的参数传递方式

  版权声明未经作者允许,严禁用于商业出版,否则追究法律责任。网络转载请注明出处,这是对原创者的起码的尊重!!!


1 传值

   C/C++默认的采用传值,即在函数被调用的时候,给形参申请一个空间,再将实参的值传递给形参,对形参的任何改变不会影响实参数的值:

#include<iostream>
using namespace std;
int add(int x)
{
    cout << "变化前,形式参数所在地址:" << &x << "   " << "形式参数值:" << x << endl;
    x++;
    cout << "变化后,形式参数所在地址:" << &x << "   " << "形式参数值:" << x << endl;
    return 0;
}
int main()
{
    int a = 1;
    cout << "调用前,形式参数所在地址:" << &a << "   " << "形式参数值:" << a << endl;
    add(a);
    cout << "调用后,形式参数所在地址:" << &a << "   " << "形式参数值:" << a << endl;
    return 0;
}

   输出结果如下:
    传值

  可以看到形参实参的地址不一样,说明新申请了内存空间。
  可以看到对形参的操作不影响实参。
  注:x是在函数内部定义的变量因而其作用范围是局部的(仅在该函数范围内能访问),生命周期是动态的(调用该函数时候创建,函数调用完成后就消除。)

2 传址

2.1 传指针

  所谓传址又叫做传指针,即在函数被调用的时候,给形参开辟一个空间用来存放传递过来的地址,将实参所在的内存地址传递给形参,对形参的任何改变也不会影响实参所指的内容,但是对形参所指的内容的改变将会影响到实参所指的内容(因为这两个指针都指向同一个内存空间)

#include<iostream>
using namespace std;
int fun(int *x,int *y)
{
    cout << "变化前,指针x所在的地址:" << &x <<"  指针y所在地址:"<< &y <<endl;
    cout << "变化前,指针x的值      :" << x << "  指针y的值    :" << y<<endl;
    cout << "变化前,指针x所指的值  :" << *x<< "             " <<"  指针y所指的值:"<< *y<<endl;
    x++;
    (*y)++;
    cout << "变化后,指针x所在的地址:" << &x <<"  指针y所在地址:"<<&y<<endl;
    cout << "变化后,指针x的值      :" << x  <<"  指针y的值    :" << y<<endl;
    cout << "变化后,指针x所指的值  :" << *x<< "             " <<"  指针y所指的值:"<< *y<<endl;
    return 0;

}
int main()
{
    int n1 = 1,n2=1;
    int *a = &n1;
    int *b = &n2;
    cout << "调用前,指针a所在的地址:" << &a <<"  指针b所在地址:"<<&b<<endl;
    cout << "调用前,指针a的值      :" << a  <<"  指针b的值    :" << b<<endl;
    cout << "调用前,指针a所指的值  :" << *a<< "             " <<"  指针b所指的值:"<< *b<<endl;
    fun(a,b);
    cout << "调用后,指针a所在的地址:" << &a <<"  指针b所å¨地址:"<<&b<<endl;
    cout << "调用后,指针a的值      :" << a  <<"  指针b的值    :" << b<<endl;
    cout << "调用后,指针a所指的值  :" << *a<< "             " <<"  指针b所指的值:"<< *b<<endl;
    return 0;
}   


  运行下结果如下:
    传址
  指针a和指针x所在地址不同说明新申请内存空间用以存放传来的地址。
  对指针x的值的改变不会改变指针a的值,也不会改变指针a所指的值,所以输出结果为1。
  对指针y所指的值的改变会改变指针b所指的值。所以输出结果为2。

2.2 传数组

  传数组是传址的另一方式,数组作为形参传递,实质传递的数组的首地址,一维数组形参 :数据类型 数组名[],二维数组形参:数据类型 数组名[][上界]
  注意:数组在传递时会退化为指针,因而要传入数组长度。

3 传引用

3.1 传引用

  引用是什么?C++中的引用可以理解为typedef的作用(C中是没有此用法),引用相当于是实参的别名,对形参的任何操作,就是对实参的操作,函数调用时不会再内存中新开辟空间。

#include<iostream>
using namespace std;
int add(int &x)
{
    cout << "变化前,形式参数所在地址:" << &x << "   " << "形式参数值:" << x << endl;
    x++;
    cout << "变化后,形式参数所在地址:" << &x << "   " << "形式参数值:" << x << endl;
    return 0;
}
int main()
{
    int a = 1;
    cout << "调用前,形式参数所在地址:" << &a << "   " << "形式参数值:" << a << endl;
    add(a);
    cout << "调用后,形式参数所在地址:" << &a << "   " << "形式参数值:" << a << endl;
    return 0;
}

  运行结果如下:

    传引用

  可以看到实参和形参的地址是相同的,也就是说并没有开辟一个新的空间。对引用的操作就是对实参的操作。

3.2 传指针的引用

  其形式为function(数据类型* &指针名),这里的指针名就是引用,就是传来的指针的别名。对它的操作就是对实参指针的操作(类似于C中的二级指针。),对它所指的值的操作,就是对实参指针所指的值的操作。

#include<iostream>
using namespace std;
#define ok 0
int add(int* &x)
{
    cout << "变化前指针x所在的地址: " << &x << endl;
    cout << "变化前指针x的值      : " << x << endl;
    cout << "变化前指针x所指的值  : " << *x << endl;
    x++;
    cout << "变化后指针x所在的地址: " << &x << endl;
    cout << "变化后指针x的值      : " << x << endl;
    cout << "变化后指针x所指的值  : " << *x << endl;
    return ok;
}
int main()
{
    int c = 1;
    int *a = &c;
    cout << "调用前指针a所在的地址:" << &a << endl;
    cout << "调用前指针a的值      :" << a << endl;
    cout << "调用前指针a所指的值  :" << *a << endl;
    add(a);
    cout << "调用后指针a所在的地址:" << &a << endl;
    cout << "调用后指针a的值      :" << a << endl;
    cout << "调用后指针a所指的值  :" << *a << endl;
    return ok;
}

  运行结果如下:

    指针的引用

  可以看到调用时没有在内存中开辟空间存储传递来的地址。对形参的改变就是对实参的改变。

4 总结

  一般时候对传入的实参如果要做改变,或传入的数据非常大时候,C++中优先考虑传引用(C/C++都可以传址,然后对指针所指内容做改变),这样调用函数时可以节约拷贝的时间和空间;如果对传入的实参不做改变可以传值、传引用、传址。

  传引用有些时候可以避免未初始化的错误。

#include<iostream>
using namespace std;
#define ok 0
struct linknode
{
    int data;
    linknode *next;
};
typedef linknode linklist;
int initlist(linklist *L)
{
    L = (linknode*)malloc(sizeof(linknode));
    return ok;
}
int main()
{
    linklist* L;
    initlist(L);
}

  这里由于在主函数定义了指针变量L后没有初始化赋值,因而出现未初始化的错误。将int initlist(linklist *L)改成int initlist(linklist *&L)就可以免于此错误。

#include<iostream>
using namespace std;
#define ok 0
struct linknode
{
    int data;
    linknode *next;
};
typedef linknode linklist;
int initlist(linklist *L)
{
    L = (linknode*)malloc(sizeof(linknode));
    return ok;
}
int main()
{
    linklist *L;
    cout<<&L
    initlist(L);
}

  版权声明未经作者允许,严禁用于商业出版,否则追究法律责任。网络转载请注明出处,这是对原创者的起码的尊重!!!


  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝月心语

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值