当你将参数传递给函数时,有两种方式:传值传递(pass by value)和引用传递(pass by reference)。让我使用一个简单的C++示例来说明这两者之间的区别,并通过可视化来帮助你理解。
我们将编写一个函数,它接受一个整数作为参数,然后在函数内部对这个参数进行修改。首先,我们来看看传值传递和引用传递的区别。
传值传递(Pass by Value)
#include <iostream>
void modifyValue(int x) {
x = 10; // 在函数内修改参数的值
}
int main() {
int num = 5;
modifyValue(num);
std::cout << "num after function call: " << num << std::endl;
return 0;
}
在这个示例中,我们定义了一个 `modifyValue` 函数,它接受一个整数 `x` 作为参数,并将 `x` 的值修改为 10。然后在 `main` 函数中,我们声明了一个整数 `num` 并将其初始化为 5,然后调用了 `modifyValue(num)` 函数。让我们来看一下这个示例的可视化:
1. `main` 函数开始时,`num` 的值是 5。
2. 我们调用 `modifyValue(num)` 函数,并将 `num` 的值作为参数传递给函数。
3. 在 `modifyValue` 函数内,`x` 的值被修改为 10。
4. 但是,在函数调用结束后,`num` 的值仍然是 5。这是因为在函数内部,我们修改的是 `x` 的副本,而不是 `num` 本身。
可视化示意图:
main modifyValue
+---+ +---+
|num| | x |
+---+ +---+
| |
| (call) |
+--------------------->|
| |
| |
| |
| |
| (modify) |
+--------------------->|
| |
| |
| |
| |
+<---------------------+
| |
+---+ +---+
|num| | x |
+---+ +---+
| 5 | | 10|
+---+ +---+
如图所示,`num` 的值在函数调用后没有被修改,因为我们传递的是 `num` 的一个副本,而在函数内部修改的是 `x`。
引用传递(Pass by Reference)
现在,让我们看看使用引用传递的情况:
#include <iostream>
void modifyReference(int &x) {
x = 10; // 在函数内修改参数的值
}
int main() {
int num = 5;
modifyReference(num);
std::cout << "num after function call: " << num << std::endl;
return 0;
}
在这个示例中,我们定义了一个 `modifyReference` 函数,它接受一个整数的引用 `x` 作为参数,并将 `x` 的值修改为 10。然后在 `main` 函数中,我们声明了一个整数 `num` 并将其初始化为 5,然后调用了 `modifyReference(num)` 函数。让我们来看一下这个示例的可视化:
1. `main` 函数开始时,`num` 的值是 5。
2. 我们调用 `modifyReference(num)` 函数,并将 `num` 的引用作为参数传递给函数。
3. 在 `modifyReference` 函数内,`x` 的值被修改为 10。
4. 由于我们传递的是 `num` 的引用,函数内部的修改也影响了 `num` 本身。
可视化示意图:
main modifyReference
+---+ +---+
|num| | x |
+---+ +---+
| |
| (call) |
+--------------------->|
| |
| |
| |
| |
| (modify) |
+--------------------->|
| |
| |
| |
| |
+--------------------->|
| |
+---+ +---+
|num| | x |
+---+ +---+
| 10| | 10|
+---+ +---+
如图所示,使用引用传递,函数内部的修改影响了 `num` 本身,因此在函数调用结束后,`num` 的值变成了 10。
总之,使用引用传递可以使函数修改原始变量的值,而不是操作其副本。这对于在函数内部修改数据并将更改传递回调用者非常有用。
但是
在传值调用中,函数无法直接改变原始变量的值,但可以通过返回新的值并将其分配给原始变量来达到相同的效果。这是如何做的:
#include <iostream>
int modifyValue(int x) {
x = 10; // 在函数内修改参数的值
return x; // 返回修改后的值
}
int main() {
int num = 5;
num = modifyValue(num); // 通过返回值来更新num
std::cout << "num after function call: " << num << std::endl;
return 0;
}
在这个示例中,modifyValue
函数接受一个整数 x
作为参数,将其修改为 10,并通过返回值返回新的值。在 main
函数中,我们通过将函数的返回值分配给 num
变量来更新 num
的值。这样,我们就可以在传值调用的情况下实现改变变量 num
的效果。
在这种情况下,modifyValue
函数返回一个整数值,但不会创建额外的数据结构或分配额外的内存空间。函数内部的变量 x
是一个局部变量,它的生存期仅限于函数的执行。一旦函数返回,这个局部变量就被销毁,不会增加额外的内存开销。
使用引用传递直接修改变量的情况:
在这种情况下,modifyReference
函数接受一个整数的引用,它并不会创建新的数据结构或分配额外的内存空间。函数内部的引用 x
简单地引用了 main
函数中的 num
变量,因此不会增加额外的内存开销。引用的本质是对现有变量的别名,不会占用额外的内存。