(以下均为个人理解)
函数访问的传参两种方式大致为:
- 值传递;
- 地址传递。
但是实际上可以都理解为,传进来的【形参】是主函数里的实参值的【一种复制】。
举个例子,哪怕我们将地址作为子函数的输入变量,形参依然只是一种复制,只在子函数运行期间存在:
#include <stdio.h>
#include <stdlib.h>
void swap(int* a, int* b)
{
printf("a is %p, b is %p
", a, b);
int* t = a;
a = b;
b = t;
printf("a is %p, b is %p
", a, b);
printf("a is %d, b is %d
", *a, *b);
}
int main()
{
int a = 5, b = 10;
swap(&a, &b);
printf("a is %d, b is %d
", a, b);
system("pause");
}
可以看到,在函数运行的过程中,a=5和b=10两个int数字的地址都被成功传入,并且完成了交换。
但是因为地址交换只发生在了子函数中。
所以仅仅是地址的交换对于主函数中值修改是无意义的。
那么为什么可以通过指针作为参数交换变量。
参考上面这段代码,这段代码没有改变传进来的a和b的地址,而是改变了a和b指针指向的值。
所以在函数运行后什么会保存。
指针指向的值。
也就是【指针】和【指针指向的内存里存储东西】的映射关系会被保存。
并不是牵扯到地址就会决定性地改变变量。
也就是,只有改变值才会被保存。
考虑到我们之前接触过的【结构体指针】。
指针作为传参形式的好处是可以节约空间。
根据我们上文中提到的子函数的形参是实参的一份复制来看,无论什么放在里面都是复制了那一份实参作为形参。
而拷贝指针,就可以只拷贝很少的空间。
再来说【数组】。
子函数中,对于数组的【修改】(非只读,包含写)都是会修改主函数的值的。
我理解为【数组操作】就是对于数组的地址中的内容进行修改。
因此子函数中对数组的操作会对主函数中产生影响。
再说C++的引用。
C++中的引用使用方式大致如下:
#include <iostream>
#include <stdlib.h>
using namespace std;
void swap2(int& a, int& b)
{
int t = a;
a = b;
b = t;
}
int main()
{
int a = 3, b = 4;
swap2(a, b);
cout << a << " " << b << endl;
system("pause");
}
引用看起来就很简单,对于需要修改值的形参传入的时候在前面写&,不需要的不写就行了。
【总结】
- 函数形参都是暂存量,只有修改指针的指向关系(地址->值的映射关系)才会被保存,也是看起来使用地址、使用指针能让子函数修改主函数值的原因。
- 引用使用起来最方便。
【更新】
考虑全局变量的存在,其实主函数中的变量只是存在了主函数时间的变量。