🔷 第七章 数组、指针和引用
📄 一句话概括

引用就是给变量起的"别名"(外号)。int &r = a; 之后,r 和 a 是同一个东西的两个名字——改 r 就是改 a。它干的事和指针有重叠(都能"改原件"),但更安全、更好写:不会为空、不用写 *、也不用写 &。这是 C++ 相对 C 的一项重要改良。

📝 本节和前面几节的关系

7.6.1 用指针对付了"改原件"这件事,但写法有点啰嗦:定义里要写 *a,调用时要写 &x,两处都容易漏。引用给出第三种、也是最漂亮的写法。它和指针是"表亲"——底层多半还是地址,但语法层面被包装成了"普通变量",把易错的地方藏起来了。第 8 章会大用特用。

一、和指针的唯一一句话区别

指针 引用
是什么 一个变量,里面存着别人的地址 一个别名,根本不是新变量
生活比喻 一张写着地址的纸条 给同一个人起的外号

外号的核心特点:叫"老王"和叫"王建国",喊的都是同一个人。不存在"这个外号指向别人"的说法——这就是引用不能改绑的原因(下面第二节)。

二、本节三篇分工

小节 覆盖什么
7.8.1 引用概述 引用是什么、三条铁律、与指针对比
7.8.2 使用引用传递参数 最有用的场景:把 swap 写成最漂亮的样子
7.8.3 使用数组作为函数参数 数组传参的真相:它其实一直在"传地址"

三、动手 Demo:先感受一下"同一个人的两个名字"

#include <iostream>
using namespace std;

int main() {
    int  a = 10;
    int &r = a;                     // r 是 a 的别名(& 在这里读作"引用")

    cout << "a = " << a << ",  r = " << r << endl;      // 10, 10

    r = 20;                          // 改 r
    cout << "改 r 之后:a = " << a << endl;             // 20  ← a 跟着变

    a = 35;                          // 改 a
    cout << "改 a 之后:r = " << r << endl;             // 35  ← r 跟着变

    cout << "两个名字,同一块内存:&a = " << &a
         << "  &r = " << &r << endl;                    // 两个地址完全相同
    return 0;
}

看到什么算成功:a = 10, r = 10、改 r 之后:a = 20、改 a 之后:r = 35;最后一行两个地址一模一样。

最后那行是本节的核心证据:&a 和 &r 打印结果相同——说明 r 不是"另开一块内存记录 a 的地址"(那是指针),而是和 a 共用同一块内存、只是多了个名字。

30 秒实验:试着写 int &r2;(声明时不初始化)——编译器直接报错('r2' declared as reference but not initialized)。这就是下一节第一条铁律的现场证据。

四、常见误区

  1. "引用就是指针的另一种写法"——底层可能都用地址实现,但语法层面完全不同:引用不能被重新绑定、不能为空、用起来像普通变量。
  2. "引用也占一块内存"——概念上它不是变量,不"另占"空间(编译器怎么实现是它的事;有些编译器内部仍用地址,但你不需要关心)。
  3. "引用太新,是不是不常用"——恰恰相反。现代 C++ 里函数参数大量使用引用(尤其是 const 引用),它是日常写法。
自测三问(点开对答案) 1. 引用和指针最根本的区别是什么?——指针是**变量**(存地址、可改指、可为空);引用是**别名**(不是新变量、不能改绑、不能为空)。 2. `int &r = a;` 之后,`r = 20;` 改的是谁?——**就是 `a`**。它们是同一个东西。 3. 引用在什么时候最有用?——函数参数(想改原件、想避免大对象拷贝),见 7.8.2。

相关笔记