上一课标准答案不能。因为a是test()里的局部变量只能在test()的作用域里使用。输出6 6因为每次调用test()都会重新创建一个新的a 5然后a变成 6。3.可以。因为a定义在外层main()里内层if可以访问外层变量。4.b定义在if的{}里面离开这对花括号后它的作用域就结束了所以外面不能直接使用。第 13 课值传递 —— 为什么函数里改了外面却没变这一课非常重要因为它直接通向后面的引用 指针 * 函数参数 数组 对象 机器人状态修改先看一个很奇怪的例子。#include iostream void change(int a) { a 100; } int main() { int x 5; change(x); std::cout x std::endl; return 0; }你可能会直觉地觉得change(x)里面把a改成了 100那x应该也变成 100。但实际输出是5为什么1. 关键a和x不是同一个变量看调用change(x);假设x 5;调用函数时C 会把x的值5复制一份交给函数参数int a所以可以想象成main 里面 x ┌─────┐ │ 5 │ └─────┘ 调用 change(x) 复制一个 5 ↓ change 里面 a ┌─────┐ │ 5 │ └─────┘注意x和a是两个不同的盒子。只是开始时里面都放着 5。2. 函数里面改的是a执行a 100;于是变成main x ┌─────┐ │ 5 │ └─────┘ change a ┌─────┐ │ 100 │ └─────┘所以改的是a不是x函数结束以后a消失。而x从头到尾还是53. 这就叫“值传递”专业名字pass by value值传递意思是把变量里的“值”复制一份传进去。不是把原变量本身交进去。4. 再看一个更明显的例子void addOne(int number) { number; }然后int main() { int count 10; addOne(count); std::cout count std::endl; }调用时count 10复制给number 10然后函数里number;变成number 11但是count依然10所以最后输出105. 用“复印件”理解最简单你可以把值传递理解成你把文件复印一份给别人。原文件x 5复印件a 5别人把复印件改成a 100你的原文件x 5不会自动变化。这就是值传递最好的直觉。6. 那为什么之前calculateError没问题之前我们写double calculateError(double target, double current) { return target - current; }调用double result calculateError(50.0, 20.0);这里我们根本不需要修改外部变量。函数只是拿到两个值 ↓ 计算 ↓ 返回结果所以值传递非常合适。7. 值传递什么时候特别常见例如double square(double x) { return x * x; }调用double result square(3.0);我们只是想让函数计算3 × 3并不希望外面的变量被改掉。所以值传递非常安全。8. 一个机器人例子double limitAngle(double angle) { if (angle 90.0) { angle 90.0; } return angle; }调用double joint_angle 120.0; double safe_angle limitAngle(joint_angle);函数收到angle 120然后改成angle 90返回90所以safe_angle 90但原来的joint_angle仍然是120因为传进去的是副本。9. 这其实有好处值传递的一个优点就是函数内部乱改参数不会影响外面的原变量。例如void test(int x) { x 999; }你在外面int motor_id 2; test(motor_id);motor_id不会突然变成 999。这能减少很多意外修改。10. 但是有时候我们就是想改外面的变量比如int speed 10;我写一个函数void setSpeed(int speed) { speed 100; }然后setSpeed(speed);你可能希望外面的speed变成 100。但值传递下它不会变。这时候就需要下一阶段的重要概念引用 reference也就是不过我们这一课先把“值传递”彻底吃透。11. 再看一遍完整程序#include iostream void change(int a) { a 100; std::cout Inside: a std::endl; } int main() { int x 5; change(x); std::cout Outside: x std::endl; return 0; }执行过程x 5 ↓ 调用 change(x) ↓ 把 5 复制给 a ↓ a 5 ↓ a 改成 100 ↓ 输出 Inside: 100 ↓ 函数结束 ↓ a 消失 ↓ 回到 main ↓ x 还是 5 ↓ 输出 Outside: 5所以Inside: 100 Outside: 512. 参数名不需要和外面一样例如void printValue(int number) { std::cout number std::endl; }外面int age 20; printValue(age);调用时age 的值 20 ↓ 复制给 number所以number 20变量名字不需要一样。13. 就算名字一样也还是两个变量看void change(int x) { x 100; } int main() { int x 5; change(x); std::cout x std::endl; }这里函数参数也叫x外面也叫x但是它们仍然不是同一个变量。可以想象成main 房间里的 x 5 change 房间里的 x 5名字相同不代表同一个东西。最终还是输出514. 参数本质上也是函数内部的局部变量这和上一课正好接上。void change(int a)这里a就是change()内部的一个局部变量。只不过它的初始值由调用者传进来。例如change(20);相当于函数开始时a 20函数结束后这个a的生命周期结束。15. 一个容易误解的机器人例子假设void stopMotor(double speed) { speed 0.0; }然后int main() { double motor_speed 100.0; stopMotor(motor_speed); std::cout motor_speed std::endl; }你可能觉得stopMotor()不是把速度改成 0 了吗但这里只改了函数里的speed所以输出还是100这就是为什么理解值传递非常重要。以后你看到真实机器人代码时如果一个函数“明明改了参数但外面没变”首先就要检查是不是值传递16. 值传递的核心图把这个牢牢记住外部变量 x 5 │ │ 复制值 ▼ 函数参数 a 5 │ │ 修改 ▼ a 100 外面的 x 仍然 5不是x 和 a 指向同一个盒子这个“同一个盒子”的效果下一课的引用才会出现。本课小练习第 1 题void change(int a) { a 20; } int main() { int x 5; change(x); std::cout x std::endl; }最后输出什么第 2 题void addTen(int number) { number 10; std::cout number std::endl; } int main() { int x 3; addTen(x); std::cout x std::endl; }依次输出什么第 3 题为什么void change(int a) { a 100; }不能直接改变外面的int x 5;第 4 题一句话解释什么是值传递