第 7 课

指针

一句话答案:指针是装着内存地址的变量。&x 给出 x 的地址;*p 给出 p 所存地址上的值。

指针就是这样一个地址

#include <iostream>
using namespace std;

int main() {
    int x = 42;
    int *p = &x;
    cout << "x = " << x << endl;
    cout << "*p = " << *p << endl;
    return 0;
}

p 装着 x 的地址,所以 *p 透过指针读到的还是 42。地址那个数字本身在本站的浏览器引擎里无法用 cout 打印 —— 真实编译器会按十六进制打出来。

存下来,再透过它读写

#include <iostream>
using namespace std;

int main() {
    int x = 42;
    int *p = &x;      // p 装着 x 的地址

    cout << *p << endl;   // 42 —— 透过指针读
    *p = 99;              // 透过指针写
    cout << x << endl;    // 99 —— x 变了
    return 0;
}

机制就这么点:p 指向 x,所以透过 p 写就是写到 x。这正是「一个函数能改另一个函数的变量」的原理。

谁需要它

要改调用方的变量,就把它的地址传进去:

#include <iostream>
using namespace std;

void doubleIt(int *p) {
    *p = *p * 2;
}

int main() {
    int n = 21;
    doubleIt(&n);
    cout << n << endl;   // 42
    return 0;
}

因为参数是地址,函数改的是调用方的 n。按值传 n 只会改一份拷贝。三种传法对比:传值、指针、引用。

数组和指针是表亲

#include <iostream>
using namespace std;

int main() {
    int a[3] = {10, 20, 30};
    int *p = a;          // 数组名会退化成首元素地址

    cout << *p << endl;       // 10
    cout << *(p + 1) << endl; // 20 —— 指针算术按元素移动
    return 0;
}

这就是数组「天然按引用传」的原因:传过去的其实是首元素地址。

两条规则

指针就是 C++ 名声的来源。现代 C++ 里多数裸指针已被引用和智能指针取代 —— 该用什么,见现代 C++ 路线图。

配套练习

下面这几道题练的正是刚讲的内容: