C++ 内存分区模型简介

目录

🧠 一、C++ 程序运行时的四大内存区域详解

📦 1. 代码区(Code Segment / Text Segment)

🔹 存放内容:

🔹 特点:

🔹 示例:

🌍 2. 全局区(Global / Static Area)→ 也叫“静态存储区”

🔹 存放内容:

🔹 特点:

🔹 示例:

🧱 3. 栈区(Stack)

🔹 存放内容:

🔹 特点:

🔹 生命周期:

🔹 示例:

🏗️ 4. 堆区(Heap)

🔹 存放内容:

🔹 特点:

🔹 生命周期:

🔹 示例:

🆚 四大区内存对比表

✅ 二、值传递时,复制出来的内容存在栈区

📌 详细解释:

🧪 示例验证:


🧠 一、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)

🔹 存放内容:

  • 程序员手动申请的内存newmalloc 等)
  • 用于存储生命周期不确定、大小动态变化的数据

🔹 特点:

  • 程序员手动分配(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/数据结构/设计模式》 - 极客文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值