一、程序运行时内存分为 4 个区
C++ 在程序运行时,会把内存划分为四个区域,不同区域存放不同数据,生命周期和管理方式也不同:
- 代码区
- 全局区 / 静态区
- 栈区
- 堆区
二、1. 代码区
- 存放程序编译后的二进制机器指令
- 特点:共享、只读
- 作用:防止程序被恶意修改、多次运行共用一份代码
- 我们一般不需要操作这里
三、2. 全局区(全局 / 静态变量区)
存放:
- 全局变量
- 静态变量 static
- 常量区(字符串常量、const 全局变量)
特点:
- 程序启动时创建,程序结束时由操作系统释放
- 未初始化的变量会自动清 0
示例:
cpp
#include <iostream>
using namespace std;
// 全局变量 → 全局区
int g_a = 10;
// 静态全局变量 → 全局区
static int g_s_b = 20;
int main() {
// 字符串常量 → 常量区(全局区一部分)
cout << "hello" << endl;
}
四、3. 栈区(stack)
存放:
- 函数内的局部变量
- 函数形参
- 函数调用现场
特点:
- 由编译器自动分配、自动释放
- 空间小、分配速度快
- 先进后出(栈结构)
- 函数结束,变量立即销毁
典型示例:
cpp
void func() {
int a = 10; // 局部变量 → 栈区
char arr[] = "abc"; // 数组 → 栈区
}
⚠️ 重要坑点:**不要返回栈区变量的地址!**函数结束后内存已释放,地址变成野指针。
五、4. 堆区(heap)
存放:
- new / malloc 出来的动态数据
特点:
- 由程序员手动分配、手动释放
- 空间大、灵活
- 不主动释放会一直存在,直到程序结束
- 容易产生内存泄漏
示例:
cpp
void func() {
// 堆区
int *p = new int(10);
}
释放:
delete p;
p = nullptr;
六、四区总结对比(超清晰)
表格
| 区域 | 存放内容 | 分配释放 | 生命周期 |
|---|---|---|---|
| 代码区 | 二进制指令 | 系统 | 整个程序运行期 |
| 全局区 | 全局 / 静态变量、常量 | 系统 | 整个程序运行期 |
| 栈区 | 局部变量、形参 | 编译器自动 | 函数内 |
| 堆区 | new 动态数据 | 手动 new/delete | 手动控制 |
七、经典面试题(必看)
1. 局部变量和全局变量区别?
- 局部变量在栈区,函数结束销毁
- 全局变量在全局区,程序结束销毁
- 全局变量默认初始化为 0,局部变量是随机值
2. 为什么不能返回局部变量地址?
局部变量在栈区,函数结束就销毁,返回的地址变成野指针,访问会崩溃或乱码。
3. new 出来的数据在哪?
在堆区,必须手动 delete,否则内存泄漏。
八、新手高频易错点
- 以为所有变量都在同一个地方
- 返回局部变量地址 / 引用,导致野指针
- 只 new 不 delete,造成内存泄漏
- 混淆栈区与堆区,导致程序莫名崩溃
- 以为静态变量和局部变量一样会自动销毁
九、今日重点总结
- C++ 内存四区:代码区、全局区、栈区、堆区
- 局部变量 → 栈(自动释放)
- 全局 / 静态变量 → 全局区(程序结束释放)
- new/malloc → 堆(手动释放)
- 严禁返回栈变量地址,堆内存必须配对释放