考虑以下 C++ 函数:
void solve(int &a, int b) {
a = a + b;
b = a - b;
a = a - b;
}
int main() {
int x = 5, y = 10;
solve(x, y);
}在 main 函数调用 solve 后,$x$ 和 $y$ 的值分别是?
这题别急着算交换,先盯紧参数定义!a 前面有个&,它是 x 的引用,改 a 就是改 x;b 没&,只是 y 的副本,改 b 不影响 y。顺着这三行代码一步步在纸上更新数值,最后看 x 和 y 各是多少。
最容易掉进 B 选项(10,5)的坑:把 b 也当成引用,以为第②步 b = a - b 会改变外面的 y。其实只有带&的形参才会穿透到实参,b 是值传递,函数里它怎么变,外面的 y 都纹丝不动。另一个坑是算错第一步加法,把 5+10 算成 15 后,第二步又误以为 b 变了导致后续减法结果不对,最后误选 D(5,5)或者 A(5,10)。记住:看&符号是判断是否影响原变量的唯一标准。
这道题考查的是 C++ 函数传参机制中引用传递与值传递的区别,以及如何在多步运算中追踪变量状态。命题人特意选了经典的“两数交换”代码片段,但把第二个参数 b 设计成值传递,就是为了挖这个坑——很多学生看到交换代码就下意识认为两个变量都会变,忽略了参数定义的细节。拿到题要先看函数头 void solve(int &a, int b),一眼识别出 a 是 x 的引用,b 是 y 的副本。接下来逐行模拟执行:
第一行 a = a + b,此时 a 指向 x(初始 5),b 是 y 的副本(10),所以 x 变成 15,b 局部保持 10。 第二行 b = a - b,这里 a 已经是 15,b 还是局部变量 10,计算得 5,赋值给局部 b,但 y 依然是 10,因为 b 不是引用。 第三行 a = a - b,a 是 15,局部 b 是 5,相减得 10,所以 x 最终变为 10。
整个过程下来,x 从 5 变到 10,y 从头到尾都是 10。正确答案是 C 选项(10,10)。
为什么这个考点高频出现?从题库数据看,运算符与表达式在 CSP 入门级共考了 12 题,但结合引用、值传递这类基础语法细节的题目,往往隐藏在程序填空或选择题里。历年趋势显示,2023 年这类题目暴增至 91 题,2024 年回落至 41 题,2025 年又回升到 61 题,说明命题人对基础语法的考察始终没有放松,只是在不同年份侧重不同。GESP 一级、二级、三级也分别考了 72、70、47 题,可见这是贯穿整个竞赛体系的必考内容。
避坑的关键在于:看到&标记就立刻反应过来“这个参数会改原变量”,没&就是“副本,改了白改”。做题时别被交换代码的表象迷惑,一定要在纸上把每一步的变量值写清楚,尤其是局部变量 b 的变化不要和全局 y 混淆。另外,注意题目问的是 main 函数调用后 x 和 y 的值,不是函数内部 b 的值,别答成局部变量状态。
基于近年考频数据,未来这类题目大概率会继续出现在入门级和 GESP 低级别,形式可能是选择题直接给代码片段问结果,或者填空题让补全参数声明。暂无足够依据预测具体年份或题型变化,但考生务必把引用与值传递的区别练到肌肉记忆,否则遇到稍微变形的交换代码就容易掉坑。