四 内存分配与释放¶
1. 内存的基本分区¶
C++ 程序运行过程中,内存通常被划分为几个区域:
区域 | 描述 |
---|---|
栈(Stack) | 函数调用时的局部变量、参数等,由编译器自动分配与释放 |
堆(Heap) | 程序员手动申请与释放的动态内存,用 new/delete 或 malloc/free 管理 |
全局区/静态区 | 全局变量、静态变量,程序运行整个生命周期都存在 |
常量区 | 字符串常量、const 常量 |
代码区 | 存放程序的指令代码 |
2. 栈内存(自动分配)¶
C++ | |
---|---|
1 2 3 |
|
特点:
- 分配、释放由编译器管理。
- 执行效率高。
- 空间有限,不适合分配大对象或长生命周期对象。
3. 堆内存(动态分配)¶
堆内存由程序员通过关键字手动管理,可以跨函数、动态申请或释放。
3.1. 使用 new
/ delete
¶
C++ | |
---|---|
1 2 3 |
|
3.2 分配数组¶
C++ | |
---|---|
1 2 |
|
2. 使用 malloc
/ free
¶
C++ | |
---|---|
1 2 3 4 5 |
|
❗ 注意:
malloc
不会调用构造函数,free
也不会调用析构函数,不推荐在 C++ 中用于对象分配。
对类对象的影响
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
4. 堆内存管理注意事项¶
问题类型 | 描述 |
---|---|
内存泄漏(Memory Leak) | 忘记 delete 或 free 导致内存无法回收 |
野指针(Dangling Pointer) | delete 后没有将指针设为 nullptr ,再使用它就会出错 |
重复释放 | 对同一个地址 delete 多次会出错(未设为 nullptr ) |
4.1 示例¶
C++ | |
---|---|
1 2 3 4 5 |
|
5. 对象的动态分配¶
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 |
|
如果是数组对象:
C++ | |
---|---|
1 2 |
|
6. 智能指针¶
手动管理内存容易出错,C++11 起推荐使用智能指针,自动管理资源:
C++ | |
---|---|
1 2 3 4 |
|
不用手动 delete
,离开作用域后自动释放,更安全更现代
智能指针是 C++11 引入的 模板类,用来 自动管理堆内存对象的生命周期,防止常见的内存泄漏和野指针问题。
智能指针会在对象不再需要时自动释放资源,相当于“带有自动释放功能的普通指针”。
6.1 三种主要智能指针类型¶
智能指针类型 | 简介 | 所需头文件 |
---|---|---|
std::unique_ptr |
独占式拥有,不能共享 | <memory> |
std::shared_ptr |
共享式拥有,引用计数管理 | <memory> |
std::weak_ptr |
弱引用,不拥有资源,防止循环引用 | <memory> |
std::unique_ptr
(独占式)
只能有一个 unique_ptr
拥有某个对象的所有权,不能复制,但可以转移
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
std::shared_ptr
(共享式)
多个 shared_ptr
可以共享同一个对象,内部使用引用计数来管理内存
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
std::weak_ptr
(弱引用)
用于配合 shared_ptr
,防止循环引用,它不会增加引用计数。
循环引用问题:
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 |
|
解决方案:使用 weak_ptr
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 |
|
6.2 原理简介(以 shared_ptr
为例)¶
- 每个
shared_ptr
指向的对象都有一个 控制块(control block)。 -
控制块中保存:
-
引用计数(shared)
- 弱引用计数(weak)
- 指针本体
当 shared_ptr
最后一个引用销毁时,析构被调用;但只有当所有 weak_ptr
也销毁后,内存才会被释放。
6.3 使用注意事项¶
项 | 建议/说明 |
---|---|
不要混用 shared_ptr 和原始指针 |
防止重复释放 |
避免 shared_ptr 循环引用 |
使用 weak_ptr |
不要 delete 智能指针指向的对象 |
会出错,智能指针自动释放 |
使用 make_shared 比 shared_ptr(new T) 更高效 |
减少内存碎片和分配次数 |
裸指针方式(容易忘记释放):¶
C++ | |
---|---|
1 2 3 |
|
智能指针方式:¶
C++ | |
---|---|
1 2 |
|
6.4 总结¶
类型 | 所有权 | 可复制 | 引用计数 | 自动释放 | 应用场景 |
---|---|---|---|---|---|
unique_ptr |
独占 | ❌ | 否 | ✅ | 独立对象 |
shared_ptr |
共享 | ✅ | 是 | ✅ | 多人共享的资源 |
weak_ptr |
弱引用 | ✅ | 不增计数 | ❌(配合 shared_ptr 使用) |
解决循环引用问题 |