函数传参右三种方式:传值,传址,传引用;
一般传值可以是变量也可以是常量
1.按值传递
(1)形参和实参各占一个独立的存储空间
(2)形参的存储空间只有是函数被调用的时候才给分配的,调用开始,系统为形参开辟一个临时的存储区(栈区),然后将各实参传递给形参,这是形参就得到了实参的值。
实例代码:
#include <stdio.h>
void swap(int x,int y)//^ 定义两个形参(数据类型一定要和实参保持一致)
{
//^ 进行交换
int tmp = x;
x = y;
y = tmp;
//^ 输出交换后的两个数
printf("x = %d y = %d\n",x,y);
}
int main()
{
int a = 2;
int b = 3;
swap(a,b);//^ 将 a 和 b 的值作为实参传给 swap 函数
//^ 检查一下 a 和 b 的值有没有交换
printf("a = %d b = %d\n",a,b);
return 0;
}
输出结果:
代码分析:
也许你会疑惑,a和b的值明明在函数swap中交换,为什么mian函数中输出的值却没有变呐?
这就得对实参和形参的关系进一步解析啦。函数传值只是单恋,并不是双向奔赴,函数的定义是:返回类型--函数名--形参;当函数被调用的时候将实参的值临时拷贝给形参存储在栈区。但是在函数中形参无论怎样改变,都不会传给实参,所以舔狗舔到最后一无所有(滑稽)。函数在调用完之后会释放给形参临时申请的空间。
2.地址传递
地址传递与值传递的不同在于:他把实参的存储地址 传送给形参,使得形参和实参指针指向同一地址,就相当于知道了人家的家庭住址,这还了得。因此,被调用的函数中对形参指针所指向的地址中内容的任何改变都会影响到实参。
实例代码:
#include <stdio.h>
void swap(int *px,int *py)//^ 因为实参传过来的是指针(地址),所以定义数据类型为整形指针
{
int tmp = *px;//^ (*指针)解引用--就是获取该地址内保存的数据。
*px = *py;
*py = tmp;
printf("x = %d y = %d\n",*px,*py);
}
int main()
{
int a = 10;
int b = 20;
swap(&a,&b);
//^ 调用了 swap 函数,同样也有看不到的操作:px = &a;py = &b;
printf("a = %d b = %d\n",a,b);
return 0;
}
输出结果:
代码分析:
从结果可以看出,形参x,y的改变也会影响实参a,b的值。因为他们都是指向同一指针的变量。无论你是对实参还是形参做出改变,都是改变的同一个指针指向的值,一把锁但有两个一样的钥匙都可以打开,对里面的内容进行改动。
3.传引用(C++)
引用传递是C++中的一种给函数传参的方式,即以引用为参数传给实参。既可以使得对形参的任何操作都能改变相应数据,又使函数调用方便。引用传递是在形参调用前加入引用操作符”&“。引用为实参的别名,和实参是同一个变量,相当与一个人有两个名字,实参是大名,形参是小名。则他们的值也是相同的,该引用改变则他的实参也改变,顺便说一下哈,传引用的实参和形参是双向传递,人家是双向奔赴。
代码实例:
#include <stdio.h>
#include <windows.h>
#include <iostream>
void swap(int &x,int &y)//^ 这里"&"并不是取地址的意思
{
int tmp = x;
x = y;
y = tmp;
printf("x = %d y = %d\n",x,y);
}
int main()
{
int a = 2;
int b = 3;
swap(a,b);
printf("a = %d b = %d\n",a,b);//^ 调用方式和传值一样
system("pause");
return 0;
}
//! 传引用的实参和形参是双向传递
输出结果:
代码分析:
我么看到该代码中只与传值方式的函数定义不同,该函数参数中都加了取地址符号&,有了这个函数会将a,b分别代替了x,y这样函数里面d操作对象就是对a,b本身了。
4.对于值传递和引用传递的比较
在c语言中,并没有引用的概念,引用时C++的概念。
在C++的函数参数中,有两种形式,其中TYPE & var 的形式,称为传引用方式;TYPE var的形式,称为传值。
二者的区别为,当传引用时,实际传到函数中的形参,是实际参数的一个引用,而不是仅传递值到函数中。具体的表现有以下几条:
- 1 传引用时,形参和实参是同一个变量,即使用相同的内存空间,二者有相同的地址。而传值时二者地址不同;
- 2 传引用时,由于没有新建变量,所以对于类对象参数,不会产生构造和析构。而如果是传值调用,调用时会进行构造,退出函数时会进行析构;
- 3 由于传引用使用的是原本实参的地址,所以对引用参数值的修改,会在退出函数后体现在主调函数中,而传值调用对参数的修改不会影响到主调函数。
- 双向传递,引用型参数命前需要加上 & ,表示这样的形参执行后会将结果回传给对应的实参