概念

指针(Pointer)

  • 一个指针变量保存的是 另一个变量的内存地址。
  • 指针本身也是一个变量,有自己的地址、类型大小、可被修改(除非是 const指针)。
  • 通过指针,你可以访问 / 操作指向那个地址的变量(前提是这个地址合法、类型匹配)。
  • 指针有可能是 “空”(nullptr或在 C 时代是NULL),意味着它不指向任何有效对象。

符号回顾:

  • T* p; 表示 p 是一个指向类型 T 的指针。
  • &x 是“取地址”操作符,给出变量 x 的内存地址(类型是 T* 如果 x 是 T)。
  • *p 是 “解引用” 操作符(dereference),它指向指针 p 所指的东西(如果合法)。

指针 = 存地址的变量

解引用 = “通过地址拿到那个地址里的值 / 对象”

引用(Reference)

  • 引用是某个变量的一个别名。换句话说,引用和它引用的对象本质就是同一个实体(在语义层面)。
  • 引用在定义时必须被初始化(必须立刻绑定到一个变量)。
  • 引用一旦绑定,就不能改指向别的东西(不能“变成”别的变量)。
  • 引用不能为 “空” —— 它总是引用一个有效的对象(至少从语言层面如此)。
  • 语法上用 T& r = x; 表示 r 是类型 T 的引用,绑定到变量 x。

在底层(编译器/实现层面)引用常被实现为指针,但在语言层面你不能把引用当作指针那样操作(不能重新赋地址、不能有空引用、不能做算术操作等)。

引用 = 给已有对象一个别名,用起来像直接用那个对象。

解引用(Dereference)

  • 解引用是指当你有指针 p,用操作符 *p 去访问 / 操作它所指向的对象(即“跳到”那个地址,拿到那个内存位置的值或进行操作)。
  • 用 * 对指针操作,就称之为解引用。
  • 注意:解引用必须保证 p 是合法指向一个对象,否则是未定义行为(会崩、出错)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
using namespace std;

int main() {
int x = 10;
int y = 20;

// —— 指针 & 解引用 示例 ——
int *p = &x; // p 是指向 int 的指针,初始指向 x
cout << "x = " << x << "\n"; // 10
cout << "p = " << p << "\n"; // 地址(x 的地址)
cout << "*p = " << *p << "\n"; // 解引用 => x 的值,即 10

*p = 15; // 通过指针修改 x
cout << "after *p = 15, x = " << x << "\n"; // x 变成 15

p = &y; // 改变指针,让它指向 y
cout << "*p now = " << *p << "\n"; // 20

// —— 引用 示例 ——
int &r = x; // r 是 x 的引用(别名)
cout << "r = " << r << "\n"; // 15(就是 x)
r = 30; // 改变 r,其实就改了 x
cout << "after r = 30, x = " << x << "\n"; // x 变 30

// 不能做的操作(会编译错误):
// int &r2; // 错:引用必须初始化
// r = &y; // 错:引用不是地址变量,不能赋地址给它

return 0;
}
1
2
3
4
5
6
7
x = 10
p = 0x7ffd1234ab58 // 示例地址
*p = 10
after *p = 15, x = 15
*p now = 20
r = 15
after r = 30, x = 30

本网站由 Nooobad 使用 Stellar 1.33.1 主题创建。
除非另有说明,本博客中的所有文章均采用 CC BY-NC-SA 4.0 许可协议。转载时请注明文章来源。