[C++]C++参数传递

关于 *和&符号、指针和地址 的基础知识可以查看此篇:[C/C++]C/C++中 *和&、指针和地址 的基本概念

1. 基本概念

  • 函数调用时要将主调函数实参的值对应传递给形参
  • 函数调用时传给形参表的实参必须与形参三个一致:类型、个数、顺序
  • 参数传递两种方式
    • 传值方式(参数为整型、实型、字符型等)
      传递的是变量的值
      传递以后,只把实参值赋值给形参。形参发生了改变,实参的值不会发生改变。
    • 传地址
      • 参数为指针变量
      • 参数为引用类型(C语言没有,C++有)
      • 参数为数组名
        数组名也是地址,数组名里面存放的数组的基地址/首元素地址

2. 传值方式

  • 代码示例
void swap(int m, int n){
	int temp;
	temp = m;
	m = n;
	n = temp;
}
void main(){
	int a, b;
	cin >> a >> b;
	swap(a, b);
	cout << a << endl << b <<endl;
}
  • 逐行解析
    传值方式示意图
    swap(a, b);
    void swap(int m, int n){......}
    a和b作为实参,传递的时候,对应的将a的值传递给m,将b的值传递给n。m和n就是形参。
    在被调用的函数swap()中,交换m和n的值。
    swap()函数执行完毕以后,m和n就被释放了,返回到main()函数调用的地方继续执行。a和b的值没有发生任何变化。

  • 总结

  1. 传递的是参数的值;
  2. 实参和形参各用各的空间;
  3. 形参发生改变,实参的值不发生改变。

3. 传地址方式

3.1 指针变量做参数

3.1.1 形参变化影响实参

  • 代码示例
void swap(int *m, int *n){
	int temp;
	temp = *m;
	*m = *n;
	*n = temp;
}
void main(){
	int a, b;
	int *p1, *p2;
	cin >> a >> b;
	p1 = &a;
	p2 = &b;
	swap(p1, p2);
	cout << a << endl << b <<endl;
}
  • 逐行解析
    int a, b;
    int *p1, *p2; 定义两个指针p1和p2
    cin >> a >> b;
    p1 = &a; p1指向a,p1指针型变量存储的是a的地址
    p2 = &b; p2指向b,p2指针型变量存储的是b的地址
    p1和p2指向a和b
    swap(p1, p2);
    void swap(int *m, int *n){......}
    将p1和p2这两个指针作为实参传递,传递给两个指针变量m和n
    p1的值传递给m,p1存储的是a的地址,所以m也存储a的地址,m也指向a;
    p2的值传递给n,p2存储的是b的地址,所以n也存储b的地址,n也指向b。
    m和n也指向a和b
    temp = *m;
    *m = *n;
    *n = temp;
    *m是取m指针变量指向的存储单元的内容,也就是a变量的值;同理*n是取b变量的内容。
    交换指针m和指针n所指的存储单元的值,即a变量和b变量的值。
    m和n所指向的存储单元交换值
    交换完之后swap()函数执行完毕,释放形参,m和n就没有了。返回到main()中调用的地方,再输出a和b值的时候,a和b的值发生了变化。

3.1.2 形参变化不影响实参

  • 代码示例
void swap(int *m, int *n){
	int *temp;
	temp = m;
	m = n;
	n = temp;
}
void main(){
	int a, b;
	int *p1, *p2;
	cin >> a >> b;
	p1 = &a;
	p2 = &b;
	swap(p1, p2);
	cout << a << endl << b <<endl;
}
  • 逐行解析
    main函数部分与3.1.1中的一致
    p1指向a,p2指向b
    将p1传递给m,m存放a的地址;p2传递给n,n存放b的地址。则m也指向a,n也指向b
    p1、p2、m和n示意图
    int *temp; 定义一个指针变量temp
    temp = m;
    指针变量temp存放m的值,m存放的是a的地址,所以temp也存放a的地址,即temp也指向a
    temp = m;
    m = n;
    n指向b,同理m指向b
    m = n;
    n = temp;
    temp指向a,同理n指向a
    n = temp;
    如上操作即交换了m和n指向的存储单元,对a和b没有任何影响。
    所以swap()函数调用完毕,m和n被释放了,返回到main()中调用的地方,a和b的值没有任何影响。

3.2 数组名作参数

  • 代码示例
//void swap(int a[]){
void swap(int * a){
    int temp;
	temp = a[1];
    a[1] = a[0];
    a[0] = temp;
}
void main(){
	int num[2] = {3, 4};
	swap(num);
	cout << num[0] << endl << num[1] << endl;
}
  • 逐行解析
    int num[2] = {3, 4}; 数组名字存的是数组中第一个元素的地址,称作数组的首地址。
    swap(num); 将数组名作为参数传递,实际上是传递一个地址,传递的是数组的首地址。
    void swap(int * a) 用地址(指针存的是一个地址)存放地址(传过来的数组的首地址)
    这时候实际上就是把整个数组传递过去了。因为数组第一个元素传递过去了,下一个元素就可以找到。
    所以对形参数组所做的任何改变都将反映到实参数组中。
    void swap(int a[]) 传递过来一个地址,用数组名a保存这个传递过来的地址,这个[]括号里不能指定大小。
    temp = a[1];
    a[1] = a[0];
    a[0] = temp;
    在被调用的函数中对形参数组进行操作,当这个操作结束也就是给a[0]和a[1]交换了值。
    所以调用结束后,输出a[0]=4,a[1]=3,实参数组num的结果发生改变。

  • 总结

  1. 数组名存的是数组的首地址
  2. 传递数组名实际上传递的是数组的首地址
  3. 传递数组的首地址来传递整个数组;
  4. 对形参数组操作实际上就是对实参数组操作。

3.3 引用类型作参数(C语言没有,C++有)

  • 引用
    引用是C++语法
    它用来给一个对象提供一个替代的名字
    引用相当于是一个别名
    int &j = i; 定义 j 是 i 的引用, j 就是 i 的别名
    操作 i 和操作 j 是一模一样的。i 的值改变, j 的值也改变;j 的值改变, i 的值也改变。
    另一个角度理解:
    &是地址,可以理解为 j 和 i 的地址是一样的。也就是说他们共用同一个空间,是同一个东西,所以其中一个改变了,另一个也跟着改变。

  • 代码示例

void swap(int & m, int & n){
	int temp;
	temp = m;
	m = n;
	n = temp;
}
void main(){
	int a, b;
	cin >> a >> b;
	swap(a, b);
	cout << a << endl << b << endl; 
}
  • 逐行解析
    swap(a, b);
    void swap(int & m, int & n)
    m是对a的引用;n是对b的引用。
    m和a用的是同一块空间;n和b用的是同一块空间。
    所以对m的任何操作实际上就是对a的操作;对m的任何操作实际上就是对a的操作。
    temp = m;
    m = n;
    n = temp;
    以上交换了m和n的值,实际上也是交换了a和b的值。
    所以对形参m和n的操作相当于对实参a和b的操作。
    引用类型作参数交换m和n

  • 总结

  1. 引用本质就是取一个别名;
  2. 引用类型作参数时其实用的是同一块空间;
  3. 对引用类型的形参的操作相当于对其实参的操作。

4. 三点说明

  1. 传递引用类型给函数与传递指针的效果是一样的,形参变化实参也发生变化
  2. 引用类型作形参,在内存中并没有产生实参的副本,它直接对实参操作
    而一般变量作参数,形参和实参就占用不同的存储单元,所以形参变量的值是实参变量的副本
    因此,当参数传递的数据较大时,用引用比用一般变量传递参数的时间和空间效率都好。在C++的参数传递中,推荐使用引用类型作为参数。
  3. 指针参数虽然也能达到使用引用的效果,但在被调函数中需要重复使用“*指针变量名”的形式进行运算,这很容易产生错误且程序的阅读性比较差;
    另一方面,在主调函数的调用点处,必须用变量的地址作为实参。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值