指针是 C++ 里最容易让新手头疼的知识点,但拆开看其实只有两个动作:取地址和解引用。这篇就用最小的例子,把指针的日常用法过一遍。

变量、地址与指针

每个变量在内存里都有自己的"门牌号",也就是地址。用 & 可以取到一个变量的地址:

#include <iostream>

int main() {
    int age = 18;
    std::cout << "age 的值: " << age << "\n";     // 输出: age 的值: 18
    std::cout << "age 的地址: " << &age << "\n";  // 输出类似: 0x7ffd...,每次运行可能不同
    return 0;
}

指针就是一个专门存放地址的变量,声明时在类型后面加 *:

int age = 18;
int* p = &age;           // p 里存的是 age 的地址

std::cout << p << "\n";  // 输出地址,如 0x7ffd...

解引用:顺着地址找到值

在指针前面加 *,就能顺着地址找到(并修改)原变量的值,这个动作叫解引用:

#include <iostream>

int main() {
    int age = 18;
    int* p = &age;

    std::cout << *p << "\n";   // 输出: 18

    *p = 20;                   // 通过指针修改 age 本体
    std::cout << age << "\n";  // 输出: 20
    return 0;
}

记住口诀:声明里的 * 表示"这是指针",使用时的 *p 表示"指针指向的那个变量"。

空指针 nullptr

指针刚声明、还没想好指向哪时,别留着不管,先给它 nullptr(表示"不指向任何地方"):

int* p = nullptr;

if (p != nullptr) {
    std::cout << *p << "\n";      // 确实指向有效地址才执行
} else {
    std::cout << "p 还是空的\n";  // 输出: p 还是空的
}

对空指针解引用是新手最常见的崩溃来源(程序直接闪退),解引用之前先判空是个值得保持的习惯。

指针与数组

数组名在大多数场合会自动变成指向首元素的指针,所以指针可以用来遍历数组:

#include <iostream>

int main() {
    int nums[] = {10, 20, 30};

    int* p = nums;            // 指向 nums[0]
    std::cout << *p << "\n";  // 输出: 10

    p++;                      // 前进到下一个元素
    std::cout << *p << "\n";  // 输出: 20
    return 0;
}

p++ 不是把地址加 1,而是跳到下一个元素,步长由元素类型决定,比如 int 通常是 4 字节。

指针和引用有什么区别

如果看过前面讲引用的那篇,你可能会问:都能"间接操作原变量",什么时候用哪个?

  • 引用必须初始化、之后不能改绑别人,用起来就像原变量本身;
  • 指针可以先不指向任何东西(nullptr),中途也能改变指向,还能做 ++ 这类运算。

简单说:确定"一直跟着某个变量"就用引用;需要"可能指向也可能不指向"或"中途换目标"时,才用指针。

小结

  • &x 取地址,int* p 声明指针,*p 解引用;
  • 暂时不需要指向时给 nullptr,解引用前先判空,避免崩溃;
  • 指针做 ++ 运算是按元素步长移动,适合配合数组使用;
  • 引用更安全简单,指针更灵活,按实际需求选择即可。