每次调用函数的时候都会重新创建形参,并用传入的实参对形参进行初始化,这就是参数传递。
1.若形参是值传递类型
它将实参的值拷贝后赋值给形参,需要注意的是,这种情况下,形参只是对实参的一份临时拷贝,它们各自有各自的内存空间,对形参进行操作并不改变实参,待函数运行完成后,操作系统就会把形参的那部分内存给释放掉。
看下面这段代码:
#include <iostream>
using namespace std;
void test1(int a){
a=10;
cout<<"形参的值为:"<<a<<endl;
cout<<"形参的地址为:"<<&a<<endl;
}
int main(){
int a1=20;
test1(a1);
cout<<"实参的值为:"<<a1<<endl;
cout<<"实参的地址为:"<<&a1<<endl;
}
输出结果如图所示:
这个过程及参数变化可以看下面这张图(每个色块表示一块内存区域,同色表示同一块内存,下面一行小字是这块内存的地址):
实际上在函数内部并不会处理实参,实参和形参在内存中是独立存在的,因此值传递并不能改变实参。
2.若形参是指针
实际上,参数是指针也可以理解为一种特殊的值传递,只不过这个值是一个指针变量而已。因此,也会在内存中为形参指针开辟一块新的区域,并用实参指针对它进行初始化,这个时候,实参指针和形参指针就会指向同一块内存,对形参指针指向的值进行操作就是对实参指针指向的值进行操作。
看下一段参数是指针的例子:
#include <iostream>
using namespace std;
void test3(int *p){
*p=10;
cout<<"形参指针的地址是:"<<&p<<endl;
cout<<"形参指针(操作的内存地址)是:"<<p<<endl;
cout<<"形参指针指向的值是:"<<*p<<endl;
}
int main(){
int a=20;
int *p1=&a;
test3(p1);
cout<<"实参指针的地址是:"<<&p1<<endl;
cout<<"实参指针(操作的内存地址)是:"<<p1<<endl;
cout<<"实参指针指向的值是:"<<*p1<<endl;
}
输出结果如图:
整个过程和参数变化可以看这幅图:
对于指针传参,我们可以理解形参指针和实参指针操作的是同一块内存,因此能够对改变指针指向的值。
3.若形参是引用传递类型
对于引用传递,形参只是实参的一个别名,并没有为形参重新开辟一块内存,对形参进行操作就是直接在实参上进行操作,能够改变实参的值。
看下面这段代码,将传参方式变成引用传递:
#include <iostream>
using namespace std;
void test2(int &a){
a=10;
cout<<"形参的值为:"<<a<<endl;
cout<<"形参的地址为"<<&a<<endl;
}
int main(){
int a1=20;
test2(a1);
cout<<"实参的值为:"<<a1<<endl;
cout<<"实参的地址为:"<<&a1<<endl;
}
输出的结果如图所示:
这个过程和参数变化可以看下面的图
这个时候实参就发生了改变,而且实参和形参在内存中的地址竟然是一样的,因为它们对应的是同一块内存区域,因此修改形参能够直接修改实参。