目录
1.值传递
将实参的值复制到形参中,在函数内部对形参的修改不会影响到实参。
下面以一段交换两个数的值为例,
#include<iostream>
using namespace std;
void swap(int x, int y) {
int temp;
temp = x;
x = y;
y = temp;
}
int main() {
int x=10, y=20;
cout << "交换前 x = " << x << endl;
cout << "交换前 y = " << y << endl;
swap(x, y);
cout << "交换后 x = "<< x << endl;
cout << "交换后 y = "<< y << endl;
return 0;
}
运行的结果如下:
按道理说,x和y的值应该发生交换,但是为什么没有发生交换呢?我们从内存的角度分析
首先定义x和y在栈区,紧接着又定义了一个函数在栈区,里面定义了一个x和y,他们的值分别是10和20,注意,这两组的x和y的地址并不是一样的(可以通过打印他们的地址来进行区分)。然后函数里面的x和y发生交换,然后这个函数结束。在这个过程中,主函数中的x和y并没有发生任何变化。这就是值传递,不管你在函数里面怎么修改,修改的只是形参,并不会影响到实参。
2.址传递
将实参的地址传递给函数的形参。函数通过这个地址来访问和操作实参。形参是一个指针变量,它指向实参所在的内存位置。在函数内部可以通过解引用指针来修改实参的值。
#include<iostream>
using namespace std;
void swap(int *x, int *y) {
int temp;
temp = *x;
*x = *y;
*y = temp;
}
int main() {
int x=10, y=20;
cout << "交换前 x = " << x << endl;
cout << "交换前 y = " << y << endl;
swap(&x, &y);
cout << "交换后 x = " << x << endl;
cout << "交换后 y = " << y << endl;
return 0;
}
运行的结果如下:
swap的参数为*x,*y,这代表的传递的一个变量的地址。还是从内存的角度进行分析。
sawp函数里面的参数是一个指针类型的变量,存的是变量的地址。假设x的地址是0x0004,y的地址是0x0008,所以函数swap里面的x的值就是0x0004,y的值就是0x0008(存的是x和y的地址)。然后分别对其进行*操作,注意此时的*代表的是取这个地址的值(要和函数参数的*区分)。*x=10,*y=20,指的就是主函数中的x和y,然后它俩进行交换。x就变成了20,y变成了10。所以,主函数的x和y就完成了交换的操作。
3.引用传递
首先我们得知道什么是引用。就是给一个变量取别名。例如:
int a=10;
int &b=a;
cout<<a<<endl;
cout<<b<<endl;
b是变量a的别名,所以b就是a,他们的值都是10.
引用传递:将实参的引用(即实参的别名)传递给函数的形参。引用就像是一个已经存在的变量的另一个名字。在函数内部对形参(引用)的操作实际上就是对实参的操作,因为形参和实参指向同一块内存空间。
#include<iostream>
using namespace std;
void swap(int &x, int &y) {
int temp;
temp = x;
x = y;
y = temp;
}
int main() {
int x=10, y=20;
cout << "交换前 x = " << x << endl;
cout << "交换前 y = " << y << endl;
swap(x, y);
cout << "交换后 x = "<< x << endl;
cout << "交换后 y = "<< y << endl;
return 0;
}
运行结果:
因为swap参数的x和y都是主函数里面x和y的别名,代表的是同一份东西,所以他们能完成交换。
总结:
传递方式 | 是否拷贝 | 是否修改实参的值 |
值传递 | 拷贝实参的值给形参 | 不能 |
址传递 | 拷贝实参的地址给形参 | 通过对形参*操作可以修改实参 |
引用传递 | 不发生拷贝 | 能 |