📖 学习信息
学习课程:黑马 C++ 零基础入门教程
本日学习:C++ 程序内存四区原理包含:内存四区整体划分、代码区、全局区、栈区、堆区、各区特点与生命周期、栈与堆区别、new/delete 动态内存分配、常见内存错误
一、前言
程序运行起来后,会在内存中划分出四块固定区域,分别是:代码区、全局区、栈区、堆区
所有变量、函数、常量、对象、动态内存,本质都分配在这四个区域里。搞懂内存四区,就能彻底理解:变量生命周期、指针原理、引用、函数传参、new/delete、野指针、内存泄漏 等底层逻辑。
二、内存四区整体介绍
程序运行时内存分为 4 大区域:
- 代码区:存放函数二进制代码、程序指令
- 全局区:存放全局变量、静态变量、常量
- 栈区:由系统自动分配释放,存放局部变量、函数形参
- 堆区:由程序员手动分配释放,手动开辟动态内存
四区核心口诀
代码只读、全局全程、栈自动释放、堆手动管理
三、各区详细讲解
1. 代码区
存放内容
- 程序编译后的二进制机器指令
- 所有函数代码、程序执行语句
特点
- 只读,不允许修改
- 共享:多个进程运行同一程序,共用一份代码区
- 程序运行期间全程存在,程序结束才释放
2. 全局区
存放内容
- 全局变量
- 静态局部变量
static - 字符串常量、const 全局常量
特点
- 程序一运行就分配,程序结束才释放
- 生命周期贯穿整个程序
- 所有函数都可以访问全局区变量
示例:全局变量与静态变量
#include <iostream>
using namespace std;
// 全局变量——存放在全局区
int g_a = 10;
void func()
{
// 静态局部变量——存放在全局区
static int s_b = 20;
s_b++;
cout << s_b << endl;
}
int main()
{
func();
func();
return 0;
}
静态变量只会初始化一次,生命周期和程序一样长。
3. 栈区(重点)
存放内容
- 局部变量
- 函数形参
- 函数调用时的现场信息
特点
- 由系统自动分配、自动释放
- 函数执行完毕,栈上变量立刻销毁
- 空间有限,不能开大数组、大对象
栈区致命规则
不要返回局部变量的地址局部变量在函数结束后立刻销毁,地址变成野指针。
错误示例:
int* getAddr()
{
int a = 10; // 局部变量,在栈区
return &a; // 错误!函数结束a销毁,返回野指针
}
4. 堆区(重点)
存放内容
- 程序员用
new手动开辟的内存 - 动态数组、动态对象
特点
-
由程序员手动开辟、手动释放
- 开辟:
new - 释放:
delete
- 开辟:
-
生命周期由程序员决定,不主动释放会内存泄漏
-
空间非常大,适合存放大数据、大数组
堆区开辟与释放基础用法
int main()
{
// 在堆区开辟一个int内存
int *p = new int(100);
cout << *p << endl;
// 手动释放堆内存
delete p;
p = nullptr; // 置空,防止野指针
return 0;
}
四、栈区 vs 堆区 核心对比
表格
| 区域 | 分配方式 | 释放方式 | 生命周期 | 空间大小 | 适用场景 |
|---|---|---|---|---|---|
| 栈区 | 系统自动 | 系统自动 | 函数结束即销毁 | 小 | 局部变量、形参 |
| 堆区 | 程序员 new | 程序员 delete | 手动控制 | 极大 | 大数据、动态内存、对象 |
记住:临时变量放栈,长久使用、大数据放堆。
五、new /delete 动态内存操作
1. 开辟单个数据
// 开辟并初始化为10
int *p = new int(10);
delete p;
2. 开辟数组
// 开辟长度为5的int数组
int *arr = new int[5];
// 释放数组要加 []
delete[] arr;
3. 内存泄漏原因
- new 之后忘记 delete
- 指针重新赋值,原来堆内存找不到了,无法释放
示例内存泄漏:
int *p = new int(10);
p = new int(20); // 原来的10没人释放,泄漏
delete p;
六、各区变量生命周期总结
- 代码区:程序启动到结束
- 全局区:程序启动到结束
- 栈区:函数调用开始 → 函数执行结束立即销毁
- 堆区:new 开辟 → 程序员 delete 释放
七、常见内存坑与避坑
- 返回局部变量地址 → 野指针、程序崩溃
- 堆内存 new 不 delete → 内存泄漏
- delete 后不置空 → 变成野指针
- 栈上定义超大数组 → 栈溢出崩溃
- 数组堆释放不用 delete [] → 内存错乱
八、今日学习总结
- 内存四区:代码区、全局区、栈区、堆区
- 代码区:只读、存函数指令
- 全局区:全局变量、static 静态变量,程序全程有效
- 栈区:局部变量、形参,系统自动分配自动释放,不能返回局部地址
- 堆区:new 手动开辟、delete 手动释放,空间大、生命周期可控
- 分清栈和堆,是看懂指针、面向对象、内存泄漏的底层基础
✍️ 下节预告
下一篇将学习 C++ 最常用的核心语法之一:引用全解,包含:引用的基础概念与语法、引用三大强制规则、引用的底层本质(常量指针)、引用做函数参数、引用做函数返回值、常引用的用法与作用,掌握引用可以替代指针简化代码、提高程序安全性,为后续面向对象编程、运算符重载打下关键基础。