指针与引用
学习目标
通过本集的学习,你将能够:
- 理解指针的概念
- 认识指针的危险
- 理解引用的概念
- 掌握内存管理基础
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 变成 1001.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 变成 1003.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=15.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=16. 自测问题
- 什么是指针?
- 指针有哪些危险?
- 引用和指针的区别是什么?
- 栈和堆的区别是什么?
- 什么是内存泄漏?
7. 下集预告
下一集我们将学习面向对象特性!
参考资料
- 《程序设计语言:概念与构造》
- 《C++ Primer》