目录
📦 1. 代码区(Code Segment / Text Segment)
🌍 2. 全局区(Global / Static Area)→ 也叫“静态存储区”
🧠 一、C++ 程序运行时的四大内存区域详解
✅ 注:不同资料可能划分略有不同(比如有的分5区、6区),但“四大区”是最经典、最通用、最教学友好的划分方式。
📦 1. 代码区(Code Segment / Text Segment)
🔹 存放内容:
- 编译后的CPU执行的二进制机器指令(编译后的代码)
- 通常是只读的,防止程序意外修改自己的指令
🔹 特点:
- 由操作系统加载和管理
- 多个进程若运行同一程序,代码区可共享(节省内存)
- 生命周期: 程序启动 → 程序结束
🔹 示例:
void myFunction() {
cout << "Hello"; // 这行代码编译后变成机器指令,存在代码区
}
🌍 2. 全局区(Global / Static Area)→ 也叫“静态存储区”
🔹 存放内容:
✅ 以下变量都存放在全局区:
| 类型 | 说明 |
|---|---|
| 全局变量 | 在所有函数外定义的变量 |
| 静态全局变量 | 加了 static 的全局变量(限制文件内可见) |
| 静态局部变量 | 函数内用 static 修饰的变量 |
| 常量 | 字符串常量、全局 const 变量(部分编译器) |
⚠️ 注意:局部 const 变量不一定在全局区!(见后文详解)
🔹 特点:
- 整个程序运行期间都存在(生命周期 = 程序运行期)
- 未初始化的全局/静态变量会自动初始化为 0
- 由系统分配和释放(程序员不用管)
🔹 示例:
int globalVar = 10; // ✅ 全局变量 → 全局区
static int staticGlobal = 20; // ✅ 静态全局 → 全局区
void func() {
static int staticLocal = 30; // ✅ 静态局部 → 全局区(生命周期延长)
const char* str = "Hello"; // ✅ 字符串常量 → 全局区(只读数据段)
const int localConst = 40; // ❗ 局部const → 通常在栈区(见后文)
}
📌 “字符串常量”一定在全局区(通常是 .rodata 只读段)
🧱 3. 栈区(Stack)
🔹 存放内容:
- 函数参数
- 局部变量(包括局部 const 变量)
- 函数调用的现场保存(返回地址、寄存器状态、参数传递、局部变量分配)
🔹 特点:
- 由编译器自动分配和释放
- 后进先出(LIFO),像“叠盘子”
- 速度快(硬件支持 + 连续内存)
- 容量有限(通常几 MB),容易栈溢出(递归太深、大局部数组)
🔹 生命周期:
- 函数调用 → 分配
- 函数返回 → 自动释放
🔹 示例:
void func(int param) { // param → 栈区
int localVar = 100; // localVar → 栈区
const double pi = 3.14159; // 局部const → 栈区(不是全局区!)
// 函数结束,以上全部自动销毁
}
🏗️ 4. 堆区(Heap)
🔹 存放内容:
- 程序员手动申请的内存(
new,malloc等) - 用于存储生命周期不确定、大小动态变化的数据
🔹 特点:
- 由程序员手动分配(new/malloc)和释放(delete/free)
- 若忘记释放 → 内存泄漏
- 若不释放,程序结束时操作系统会回收(但这是“兜底”,不能依赖!)
- 速度比栈慢(需要管理算法),但容量大(受限于物理内存+虚拟内存)
🔹 生命周期:
new→ 分配delete→ 释放(或程序结束由 OS 回收)(注意,释放数组的时候应该使用delete[] 数组名)
🔹 示例:
int* p = new int(100); // ✅ p 指向堆区的 int
delete p; // ✅ 手动释放
// 或者
student* s = new student{"张三", 18, 100};
// ... 使用 ...
delete s; // 必须手动释放,否则内存泄漏!
🆚 四大区内存对比表
| 区域 | 存放内容 | 分配/释放者 | 生命周期 | 速度 | 大小限制 |
|---|---|---|---|---|---|
| 代码区 | 函数二进制代码 | 操作系统 | 程序运行期 | 快 | 固定 |
| 全局区 | 全局变量、静态变量、常量 | 系统 | 程序运行期 | 中 | 固定 |
| 栈区 | 局部变量、函数参数 | 编译器 | 函数调用期 | ⚡ 很快 | 小(几MB) |
| 堆区 | 动态分配对象 | 程序员 | 手动控制 | 慢 | 大(GB级) |
✅ 二、值传递时,复制出来的内容存在栈区
📌 详细解释:
当你进行值传递时:
void func(student s); // ← 值传递:会复制一份!
int main() {
student stu = {"张三", 18, 100};
func(stu); // ← 这里会复制 stu,生成一个副本
}
这个“副本” s 是:
- 一个局部变量(只在
func函数内部存在) - 存放在 栈区
- 函数调用时创建,函数返回时自动销毁
🧪 示例验证:
#include <iostream>
using namespace std;
struct Student {
string name;
int age;
int score;
};
void printStudent(Student s) { // ← 值传递,s 是副本
cout << "副本地址: " << &s << endl; // 打印副本地址
// s 存在于栈区!
}
int main() {
Student stu = {"张三", 18, 100};
cout << "原对象地址: " << &stu << endl;
printStudent(stu); // 传值 → 复制 → 副本在栈区
return 0;
}
✅ 输出结果(地址不同):
原对象地址: 0x7ffee4b5a9a8
副本地址: 0x7ffee4b5a988 ← 不同地址!且是栈地址(高地址,向下增长)
→ 证明:副本是全新的对象,位于栈区
补充:
🆚 三、全局 const vs 局部 const 对比表
| 特性 | 全局 const 变量 | 局部 const 变量 |
|---|---|---|
| 定义位置 | 函数外部(全局作用域) | 函数内部 |
| 存储区域 | ✅ 全局区(通常是 .rodata 只读段) | ✅ 栈区 |
| 生命周期 | 程序启动 → 程序结束 | 函数调用 → 函数返回 |
| 初始化时机 | 编译期或程序启动时 | 函数执行到定义语句时 |
| 链接属性 | 默认内部链接(internal linkage) | 无链接(no linkage) |
| 是否可被其他文件访问 | 默认 ❌,加 extern 可 ✅ | ❌ 不可能 |
| 示例 | const int N = 100; | void f() { const int x = 10; } |
我搜到的可供参考的内容:5-内存四驱模型 - 内存四区堆栈区的理解 - 《C/C++/Qt/Win32/数据结构/设计模式》 - 极客文档

246

被折叠的 条评论
为什么被折叠?



