C/C++ 内存管理详解:从内存分布到 new/delete 原理
在学习 C/C++ 的过程中,内存管理是绕不开的核心知识。栈、堆、静态区到底有什么区别?malloc 和 new 到底差在哪?为什么 delete[] 不能写成 delete?new 底层到底做了什么?如果这些问题没有形成完整体系,后面学习 STL、智能指针、内存池、操作系统时会越来越混乱。这篇文章将系统梳理整个知识链路,帮助你真正建立对内存管理的整体认知。
C/C++ 内存管理详解:从内存分布到 new/delete 原理
前言
在学习 C/C++ 的过程中,内存管理是绕不开的核心知识。很多初学者会感觉:
- 栈、堆、静态区到底有什么区别?
- malloc 和 new 到底差在哪?
- 为什么 delete[] 不能写成 delete?
- new 底层到底做了什么?
如果这些问题没有形成完整体系,后面学习 STL、智能指针、内存池、操作系统时会越来越混乱。这篇文章将系统梳理整个知识链路,帮助你真正建立对内存管理的整体认知。
一、程序运行时的内存分布
一个 C/C++ 程序运行后,内存并不是随便使用的,而是被划分为不同区域。
通常我们会接触到以下几个区域:
1.1 栈(Stack)
栈主要存储:局部变量;函数参数;返回值
特点:由系统自动管理;生命周期随函数结束而结束,向下增长,速度快
void Test()
{
int a = 10;
}
//这里的 a 就在栈上。
1.2 堆(Heap)
堆用于动态内存申请:
int* p = (int*)malloc(sizeof(int));
特点:由程序员手动管理;需要 free/delete;生命周期由程序员决定;向上增长;灵活但容易泄漏
1.3 数据段(静态区)
用于存储:全局变量;static 静态变量
int globalVar = 1;
static int staticVar = 1;
1.4 代码段(常量区)
存储:可执行代码;字符串常量;const 常量
const char* str = "hello";
//字符串 "hello" 位于常量区。
二、理解变量“本身”和“指向内容
这是初学者最容易混淆的地方。来看经典例子:
char arr[] = "abcd";
const char* p = "abcd";
很多人以为它们一样,其实完全不同。
char arr[] = "abcd";
const char* p = "abcd";
- arr 是数组,数组本身在栈上,“abcd” 被拷贝到数组中。所以arr 在栈;arr中的字符也在栈。
- p 是指针变量,指针本身在栈上,“abcd” 字符串常量在常量区。所以p 在栈;p指向的内容在常量区
三、C 语言动态内存管理
C 中主要使用四个函数:malloc;calloc;realloc;free。
3.1 malloc
申请指定大小内存:
int* p = (int*)malloc(sizeof(int));
特点:只申请空间;不初始化,因此里面是随机值。
3.2 calloc
int* p = (int*)calloc(4, sizeof(int));
特点:申请多个元素空间;自动初始化为 0。相当于:malloc + memset(0)。
3.3 realloc
用于扩容:
p = (int*)realloc(p, sizeof(int) * 10);
分别是原地扩容和异地扩容。
3.4 free
释放动态内存:
free(p);
//free 后不要继续使用指针
p = NULL;
四、C++ 为什么引入 new/delete
虽然 C 的 malloc/free 能用,但存在很多问题:
- 需要手动计算大小;
- 返回值需要强转;
- 无法自动初始化对象;
- 无法调用构造函数/析构函数;
于是 C++ 引入:new和delete。
4.1new/delete 基本使用
//单对象
int* p = new int(10);
delete p;
//对象数组
int* arr = new int[10];
delete[] arr;
注意:new[] 必须对应 delete[]
4.2new/delete 与 malloc/free 最大区别
核心区别:malloc/free 只管理内存;new/delete 既管理内存,也管理对象。
1.malloc/free 不调用构造析构;A* p = (A*)malloc(sizeof(A));;这里只是开空间。对象并没有真正构造。
2.new/delete 会调用构造析构;A* p = new A(10);;A* p = new A(10);这里会申请空间和调用构造函数。
delete时会调用析构函数和释放空间。
4.3new[] 和 delete[] 为什么必须匹配
new[]:A* arr = new A[3];底层会:申请3个对象空间并且调用3次构造函数
delete[]:delete[] arr;调用3次析构函数并且释放空间
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)