一、C/C++内存分布
1.1.内存五大分区
1.栈:非静态局部变量、函数参数、返回值;向下增长。函数调用时临时开辟的一块内存,函数执行完这块内存就自动销毁;向下增长意思是:后开辟的变量,内存地址比先开辟的更小(地址往低地址方向走)
**2.堆:**动态内存申请,向上增长,自己手动申请的内存(new/malloc),不用了要手动释放;向上增长意思是:新申请的内存,地址比之前申请的更大(地址往高地址方向走)
**3.内存映射段:**共享库、共享内存、IO 。把磁盘上的文件、库文件直接映射到进程内存里,多个程序可以共用同一份库,不用全部拷贝到自己内存;用完由系统管理,不用自己手动申请释放。
**4.数据段(静态区):**全局变量、static静态变量。
👉通俗解释: 程序一运行就开辟、直到程序结束才销毁;所有对象共用这一块空间,变量存在这里,不会随着函数结束而消失。
**5.代码段(常量区):**可执行代码、只读字符串常量。
👉通俗解释:存放写好的程序指令和双引号里的字符串,只读不能修改;程序运行全程都在,多个进程可以共用这份代码。

1.2.实例变量内存位置辨析
1.全局/静态全局->数据段
2.局部普通变量:栈
3.static局部变量:数据段
4.字符串字面量:代码段
5.malloc申请内存:堆
// 1.全局/静态全局 -> 数据段
int g_a = 10; // 全局变量
static int sg_b = 20; // 静态全局变量
int main()
{
// 2.局部普通变量:栈
int a = 100;
// 3.static局部变量:数据段
static int s_c = 200;
// 4.字符串字面量:代码段
const char* p = "hello";
// 5.malloc申请内存:堆
int* ptr = (int*)malloc(sizeof(int));
return 0;
}
二、C语言动态内存管理
2.1.函数
1.malloc:申请size字节,不初始化,失败返回NULL

分配内存块
分配一块大小为 size 字节的内存,返回指向这块内存起始位置的指针。
举例:int* p = (int*)malloc(sizeof(int));
2.calloc:申请n个size字节,初始化为0,失败返回NULL
分配数组内存并初始化为 0
为包含 num 个元素的数组分配一块内存,每个元素占 size 字节,并且把内存里所有位全部初始化为 0。
举例:
// 申请5个int空间,每个int占4字节,全部自动初始化为0
int* arr = (int*)calloc(5, sizeof(int));
3.realloc:扩容/缩改已有内存块,返回新地址。

重新分配内存块
修改 ptr 指向的这块内存的大小。
参数说明:
ptr:之前 malloc/calloc/realloc 得到的堆内存指针;
size:调整之后新的总字节数
举例:int* tmp = (int*)realloc(p, 10 * sizeof(int));
4.free:释放堆内存,不能释放栈内存。

释放内存块
把 ptr 指向的堆内存还给操作系统。
参数:ptr 是之前 malloc /calloc/realloc 返回的堆指针
⚠️ free不会把指针本身清空,也不会把内存里的数据清零!
2.2.malloc、calloc、realloc三者的区别
malloc: 在堆区分配指定字节数的连续内存空间,不对内存内容做初始化。申请一块堆空间,里面保留原来的随机垃圾值。
calloc :在堆区分配指定数量、指定大小的连续内存空间,并将内存全部初始化为 0。申请一块堆空间,申请好直接全部置 0。
**realloc:**重新调整一块已分配堆内存的总字节大小,保留原有有效数据。给已经申请好的堆空间扩容或者缩容。
三、C++动态内存new/delete
3.1.内置类型
1.new 类型
申请空间,在堆区为单个内置类型对象分配内存,不主动初始化,返回该类型的指针。
int* p = new int;
2.new 类型(值)
申请加初始化,在堆区分配单个该类型的内存空间,同时用括号内的值完成初始化,返回对应类型指针。
int* p = new int(20);
3.new 类型N
申请N个连续的空间,在堆区分配N 个该类型、连续的内存空间(数组空间),默认不初始化,返回首元素指针。
int* p = new int5;
4.delete释放单个,delete 释放数组,必须配对
delete 用于释放由 new 开辟的单个对象内存;delete\[\] 用于释放由 new\[\] 开辟的数组内存。new 和 delete、new \[\] 和 delete \[\] 必须严格配对使用,混用属于未定义行为,程序可能崩溃、内存泄漏。
// 单个
int* p1 = new int(10);
delete p1;
// 数组
int* p2 = new int[5]{1,2,3};
delete[] p2;
3.2.自定义类型
1.new:开辟空间+调用构造函数
new 先在堆区分配内存空间,分配成功后,自动调用对应类型的构造函数完成对象初始化,最后返回对象指针。
2.delete:调用析构函数+释放空间
delete 先调用指针指向对象的析构函数,完成对象资源清理;再释放该对象在堆上的内存空间。
delete\[\] 会依次调用数组中每一个对象的析构函数,全部清理完毕后,再释放整块数组内存。
3.malloc/free:只开辟/释放空间,不调用构造/析构函数。
malloc 仅在堆区申请一块原始内存,不会调用类的构造函数;free 仅回收这块堆内存,不会调用析构函数,没有对象的初始化与资源清理逻辑。