指针与引用

学习目标

通过本集的学习,你将能够:

  • 理解指针的概念
  • 认识指针的危险
  • 理解引用的概念
  • 掌握内存管理基础

1. 指针

1.1 什么是指针?

指针是存储内存地址的变量。

指针示例(C++):
int x = 42;
int *p = &x;  // p 指向 x

内存:
地址:  100
值:    42  (x)
      ↓
p:   100  (存储 x 的地址)

1.2 指针操作

取地址:&
int x = 42;
&x  // x 的地址

解引用:*
int *p = &x;
*p  // x 的值(42)

修改:
*p = 100;  // x 变成 100

1.3 指针与数组

数组名是指向第一个元素的指针:
int arr[5] = {1, 2, 3, 4, 5};
arr == &arr[0]  // true

指针算术:
arr + 0 == &arr[0]
arr + 1 == &arr[1]
arr + 2 == &arr[2]

*(arr + i) == arr[i]

2. 指针的危险

2.1 空指针

空指针:
int *p = NULL;  // 或 nullptr
*p = 42;  // 崩溃!访问空指针

2.2 野指针

野指针(指向已释放内存):
int *p = new int;
delete p;
*p = 42;  // 危险!访问已释放内存

2.3 悬空指针

悬空指针:
int *p;
*p = 42;  // 危险!p 未初始化

2.4 缓冲区溢出

缓冲区溢出:
char buf[5];
strcpy(buf, "hello world");  // 写入超过 5 字节
// 可能覆盖其他内存,导致崩溃或安全漏洞

2.5 内存泄漏

内存泄漏:
void f() {
    int *p = new int;
    // 忘记 delete p
}  // p 丢失,内存无法回收

多次调用 f() 会耗尽内存

3. 引用

3.1 什么是引用?

引用是变量的别名。

引用示例(C++):
int x = 42;
int &r = x;  // r 是 x 的引用

r = 100;  // x 变成 100

3.2 引用 vs 指针

引用:
- 必须初始化
- 不能改变指向
- 自动解引用
- 更安全

指针:
- 可以不初始化
- 可以改变指向
- 显式解引用
- 更灵活但危险

4. 内存管理基础

4.1 内存区域

内存区域:
- 栈(Stack):局部变量,自动管理
- 堆(Heap):动态分配,手动管理
- 静态区(Static):全局变量,静态变量
- 代码区(Code):程序代码

4.2 栈内存

栈内存:
void f() {
    int x = 42;  // 栈上分配
    int y = 100;
}  // 自动释放

特点:
- 自动管理
- 快速
- 大小固定
- LIFO 顺序

4.3 堆内存

堆内存(C++):
int *p = new int;  // 堆上分配
*p = 42;
delete p;  // 手动释放

堆内存(C):
int *p = malloc(sizeof(int));
*p = 42;
free(p);

特点:
- 手动管理
- 较慢
- 大小可变
- 任意顺序

5. 实用案例

5.1 案例1:指针交换两个数

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int x = 1, y = 2;
swap(&x, &y);
// x=2, y=1

5.2 案例2:引用交换两个数

void swap(int &a, int &b) {
    int temp = a;
    a = b;
    b = temp;
}

int x = 1, y = 2;
swap(x, y);
// x=2, y=1

6. 自测问题

  1. 什么是指针?
  2. 指针有哪些危险?
  3. 引用和指针的区别是什么?
  4. 栈和堆的区别是什么?
  5. 什么是内存泄漏?

7. 下集预告

下一集我们将学习面向对象特性!

参考资料

  • 《程序设计语言:概念与构造》
  • 《C++ Primer》
« 上一篇 数据类型详解 下一篇 » 面向对象特性