C++ 竞赛入门

引用

引用

本节学会什么

  • 区分值传递和引用传递
  • int& 参数让函数修改调用者变量
  • 读懂引用声明、取地址和普通赋值的区别

为什么需要它

函数的普通参数会复制实参,因此函数内的修改默认不会影响调用者。需要交换两个变量或直接更新一个结果时,引用参数能让形参成为实参的别名。现在它紧跟在“函数参数”之后学习,首要用途就是写出会修改调用者变量的函数。

最小可运行示例

#include <iostream>

void swap_values(int& a, int& b) {
    int temporary = a;
    a = b;
    b = temporary;
}

int main() {
    int x = 3;
    int y = 5;
    swap_values(x, y);
    std::cout << x << ' ' << y << '\n';
    return 0;
}

输出是 5 3。调用 swap_values(x, y) 时,ax 的别名,by 的别名,因此函数中的赋值会修改 main 中的原变量。

关系图:引用 result 是 score 的别名,指针则保存指向 score 的地址

关键过程与易错点

  • void change(int x) 是值传递,函数中的 x 是副本;void change(int& x) 才会修改调用者变量。
  • int& a 中的 & 是“声明引用”,不是取地址。引用参数必须接收一个可修改的变量,所以 swap_values(3, 5) 是错误的。
  • 引用必须在声明时绑定到对象。给引用赋值是修改它绑定的对象,不是改绑到另一个变量。
  • &score 中的 & 才是取地址;指针会在选读页介绍。不要只靠符号判断含义,要看它是在声明还是表达式中。
  • 只读的大对象以后常写成 const std::string& text,表示“不复制,也不修改”;初学阶段先把“是否修改调用者”判断清楚。
  • 初学阶段不必追究引用在内存中的实现。判断关键是:它有没有创建副本?普通引用没有。

动手检查

分别写 void add_one(int x)void add_one_reference(int& x)。用同一个变量调用它们,比较调用后的结果。

再把最小示例中的交换函数改为 make_even(int& x):若 x 是奇数则加一。分别传入 45,确认修改发生在函数内,但结果保留在调用者变量中。

立即练习

难度 题目 题解 训练目标
基础 洛谷 P5735:距离函数 题解 为计算设计参数和返回值,再判断哪些参数需要修改。
巩固 洛谷 P5737:闰年展示 题解 将判断写成函数,并让主程序只负责读入和输出。