函数参数的传递方式:值传递、指针传递、引用传递(“引用”这一概念在C++中提出,C中没有)
在我刚开始学习时,就有很多疑惑的地方:
为什么要有这么多种方式来传递函数参数呢?
只用值传递不可以吗?
为什么要有“指针”?它有什么用吗?
C++为什么要提出“引用”?它和指针不是差不多吗?
但是,当我开始写程序时,就逐渐遇到了问题——
问题一:值传递的缺陷
#include<stdio.h>
void swap(int a,int b){
int middle;
middle=a;
a=b;
b=middle;
}
int main(){
int aa=3,bb=4;
swap(aa,bb);
printf("%d %d",aa,bb);
return 0;
}
按理说,swap()这个函数实现的就是两个数值的交换,那为什么运行结果是:
嗯?aa和bb两个变量的值并没有交换啊?
这是因为函数参数的值传递是把实参的值带入到形参中进行相应的操作的:
假设有一堵墙,墙左边是实参aa=3和bb=4,墙右边是形参:a被附上aa的值3,b被附上bb的值4;
通过middle这个变量,a和b实现了值的对调,函数执行完毕,临时变量a和b被释放。
整个过程与aa和bb这两个实参几乎无关联(除了最初aa、bb的值分别赋给a和b之外,aa、bb根本没有参与交换的过程)
因此,函数参数的值传递是有缺陷的,我们要使用“指针”来弥补这一缺陷。
解决一:使用指针传参
改进的代码是:
#include<stdio.h>
void swap(int* a,int* b){
int middle;
middle=*a;
*a=*b;
*b=middle;
}
int main(){
int aa=3,bb=4;
swap(&aa,&bb);
printf("%d %d",aa,bb);
return 0;
}
这次的运行结果:
因为这次是把指针a、b分别指向aa、bb两个变量的地址。
就比如有两个屋子(空间),变量的地址就是门牌号。一个门牌号是301,另一个门牌号是302。
指针a里存301,指针b里存302。交换的是房间里的物品3和4。
这次交换的就是这两个变量aa和bb内存空间里的值,所以即使结束后两个指针a和b被释放也没有关系,
因为指针是真真实实的通过地址,把本身变量的数据给改了。
那么指针就是万能的吗?
不是。因为指针传参的实质也是值传参。这里的“值”就是“地址值”。
那刚刚的代码为什么对了?因为刚刚我们改变的是指针指向的那个地址空间里面的变量值,而不是改变指针指向的那个地址(更准确的说是指针存放的那个地址)。
如果改变指针变量存放的地址,就会出现问题。
问题二:指针传参的缺陷:如果在函数体中改变参数指针的指向,不能真正改变这个指针
#include<stdio.h>
void change_address(int *xing){
int shi2=6;
xing=&shi2;/*改变xing这个指针的指向,传参时它指向shi1,现在指向shi2*/
}
int main(){
int shi1=5;
change_address(&shi1);
printf("%d",shi1);
return 0;
}
运行结果是:
可以看到是shi1的值没有改变。
这是因为先让形参中的指针变量指向实参,再让形参指向其他的变量。这与实参无关,道理和最上面的swap()值传递是一样的,因此可以说——
指针传参和值传参的实质是相同的。
解决二(1):类比上一例,再套一层指针
类似的推理:用值传递改变值是失败的,因此用指针代替;用指针传递改变地址是失败的,它相当于值传递,那就给它也加一个指针,变成指针的指针。
#include<stdio.h>
void change_address(int**xing){
int shi2=6;
*xing=&shi2;/*改变xing这个指针的指向,传参时它指向shi1,现在指向shi2*/
}
int main(){
int shi1=5;
int *a=&shi1;
change_address(&a);
printf("%d",*a);
return 0;
}
运行结果为:
是6,成功了。但是shi1这个变量不是指针变量,因此&shi1也不是指针的指针的形式,所以我做了小改动,定义指针变量a指向shi1,因此&a就是指针的指针的形式了。
不过这样就有些麻烦了。因此,C++中提出了“引用”。
解决二(2):使用“引用”
#include<stdio.h>
void change_address(int &xing){
int shi2=6;
xing=shi2;/*&是引用的符号,它表示xing是shi1的别名,它们是一样的*/
}
int main(){
int shi1=5;
change_address(shi1);
printf("%d",shi1);
return 0;
}
这样就很简单方便了。运行结果:
结果正确。这也是引用比指针更强大的地方。
写到这里,上面的所有问题也都有了答案,希望能给初学者带来帮助吧!
这篇文章如有错误的地方,欢迎大家批评指正哟~