动态内存管理(c++方向必看)

📅 发布时间:2026/10/2 17:39:03
动态内存管理(c++方向必看)
引言学 C 的时候我一度觉得malloc挺多余——数组不是挺好用吗直到写了个小练习让用户输入一串数字再排序。写完发现卡住了数组长度写多少写 10用户输入 11 个就崩写 1000又嫌浪费万一输入 1001 个呢。关键是到底有几个数字我写代码的时候根本不知道得等程序跑起来才清楚。malloc解决的就是这个运行时再决定要多少内存代价是这块内存从此归你管——用完得free不能越界free完也不能再用。动态内存管理也是学好数据结构的前置知识点。这篇就来讲清楚这几件事。目录1.为什么要有动态内存分配2.malloc和free2.1malloc2.2free3.开辟成功和失败的案例3.calloc和realloc3.1calloc3.3realloc1.为什么要有动态内存分配我们已经掌握的的内存开辟方式有int val 20; //在栈空间上开辟四个字节 char arr[10] { 0 }; //在栈空间上开辟10个字节的连续空间但是上述开辟空间的方式有两个特点:1.空间开辟大小是固定的2.数组在申明的时候必须指定数组的长度数组空间⼀旦确定了大小不能调整但是对于空间的需求不仅仅是上述的情况。有时候我们需要的空间大小在程序运⾏的时候才能知 道那数组的编译时开辟空间的方式就不能满足了。C语言引入了动态内存开辟让程序自己可以申请和释放空间就比较灵活了。2.malloc和free2.1mallocC语言为我们提供了一个动态内存开辟的函数void* malloc (size_t size);功能向内存的堆区申请一块连续可用的空间并返回指向这块空间的起始地址。1. 如果开辟成功则返回这块空间的起始地址。2.如果开辟失败则返回⼀个 • 返回值的类型是 NULL 指针因此malloc的返回值⼀定要做检查。3.返回值的类型是void* 所以malloc函数并不知道开辟空间的类型具体在使⽤的时候使⽤者自己来决定。4. 如果参数 size 为0malloc的行为是标准是未定义的取决于编译器2.2freeC语言提供了一个用于做动态内存的释放和回收的函数freevoid free (void* ptr);free函数用来释放动态开辟的内存就像一个图书馆不能一直借书但是从来不还书这样会出问题的malloc和free都声明在stdilb.h头文件中。如果参数ptr指向的空间不是动态开辟的那函数free的行为是未定义的。如果参数ptr是NULL指针则函数什么都不需要做。3.开辟成功和失败的案例#includestdio.h #includestdlib.h int main() { int* p (int*)malloc(20);//在堆区上申请20个字节的空间 if (p NULL) { perror(use malloc); return 1; } //使用空间 int i 0; for (i 0; i 5; i) { p[i] i 1; } //释放内存 free(p); return 0; }当程序指向完free这一行我们使用malloc开辟的内存就被回收掉了但是当我们把地址还掉之后p还指向原来的地址此时的p就是野指针这个时候给他一个空指针可以了就像给野狗套上铁链子。当我们把编译器环境从x64改成x86并且在malloc中输入特别大的数字动态内存的开辟就有可能失败错误信通过perror函数打印出来。3.calloc和realloc3.1callocC语言还提供了一个函数calloccalloc也能用来动态内存分配void* calloc (size_t num, size_t size);函数的功能是为num个⼤⼩为size的元素开辟⼀块空间并且把空间的每个字节初始化为0与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全 0。int main() { int* p (int*)calloc(5, sizeof(int)); if (p NULL) { perror(use malloc); return 1; } //使用空间 int i 0; for (i 0; i 5; i) { p[i] i 1; } //释放内存 free(p); p NULL; return 0; }malloc和calloc仅仅在初始化上有区别其他方面是没有区别的。3.3reallocrealloc的出现使得动态内存管理更加灵活有时我们会觉得内存过小不够用有时候内存过大又会产生浪费为了更合理的使用内存我们会对内存的大小做灵活调整realloc就可以做到对动态开辟内存大小的调整。void* realloc (void* ptr, size_t size);功能重新调整之前分配的内存块的大小它可以在不丢失原有数据的情况下扩大或缩小动态分配的内存块。参数ptr是要调整的内存空间的起始地址如果ptr是NULl指针realloc函数的功能类似于malloc函数。size调整之后新大小单位是字节。返回值成功:返回一个指向重新分配的内存块的void*类型指针。这个指针可能与原来的指针不同。失败:如果内存重新分配失败返回 NULL并且原来的内存块保持不变。int main() { int* p (int*)calloc(5, sizeof(int)); if (p NULL) { perror(use malloc); return 1; } //使用空间 int i 0; for (i 0; i 5; i) { p[i] i 1; } //希望空间能放10个整形 int* ptr realloc(p, 10 * sizeof(int)); if (ptr NULL) { perror(use realloc); return 1; } else { p ptr;//继续使用p来维护空间 } //继续使用 for (i 5; i 10; i) { p[i] i 1; } free(p); p NULL; return 0; }注意这里不能直接使用p来接收realloc的结果因为p本身就指向了一块空间如果realloc开辟失败那么p直接被置为NULL了所以我们可以先创建一个ptr来接收待确认空间开辟成功再让p接收。使用realloc调整空间存在两种情况1.原有的空间后有足够大的空间此时拓展内存就直接在原有内存之后直接追加内存原来空间的数据不发生变化2.当原有空间之后没有足够多的空间时扩展的方法是在堆空间另找一个合适大小连续的空间来使用并返回新的地址原来空间中存放的数据会复制过来随后旧空间就释放掉了。旧空间”我免费了“free因为篇幅原因动态内存暂时就写到这下一篇会把常见的动态内存错误一些经典的面试题柔性数组等知识点讲清楚。再次感谢各位码友的观看祝我们都能实现自己的理想