C++动态内存/内存管理
文章目录前言一、内存分区二、C 语言动态内存标准库函数1.核心函数2.代码示例3.关键注意点三、C 动态内存关键字 / 操作符1.核心用法1单个对象2数组对象3类对象2.实现原理1内置类型2自定义类型3.关键特性四、区别栈区 vs 堆区C/C 动态内存--核心区别五、常见错误前言动态内存是程序手动在堆区申请、使用、释放的内存区别于栈区内存的自动管理是 C/C 核心考点和开发必备知识点。整体分为C 语言动态内存和C 动态内存两大体系核心围绕内存分配、释放、常见错误、最佳实践展开。一、内存分区程序运行时内存分为 4 个区域动态内存仅存在于堆区栈区局部变量、函数参数系统自动分配 / 释放空间小、连续、速度快。堆区动态内存手动申请 / 释放空间大、不连续、速度慢易产生内存碎片。全局 / 静态区全局变量、static变量程序结束后系统释放。常量区字符串常量、const 常量只读不可修改。二、C 语言动态内存标准库函数依赖stdlib.h头文件核心 4 个函数malloc/calloc/realloc/free成对使用手动管理。1.核心函数函数语法功能特点mallocvoid* malloc(size_t size)申请指定字节数的堆内存不初始化内存返回void*失败返回NULLcallocvoid* calloc(size_t num, size_t size)申请num个size大小的内存自动初始化为 0参数拆分更直观reallocvoid* realloc(void* ptr, size_t new_size)调整已分配内存的大小原地扩容 / 异地扩容ptrNULL等价mallocfreevoid free(void* ptr)释放堆内存无返回值仅能释放堆内存free(NULL)安全2.代码示例#include stdio.h #include stdlib.h int main() { // 1. malloc申请4字节int内存强转类型 int* p1 (int*)malloc(sizeof(int)); if (p1 NULL) { // 必须判断防止分配失败 perror(malloc fail); return 1; } *p1 10; // 2. calloc申请5个int初始化为0 int* p2 (int*)calloc(5, sizeof(int)); // 3. realloc扩容为10个int int* p3 (int*)realloc(p2, 10 * sizeof(int)); if (p3 ! NULL) p2 p3; // 扩容成功更新指针 // 4. 释放内存后置空避免野指针 free(p1); free(p2); p1 p2 NULL; return 0; }3.关键注意点必须强转类型malloc返回void*需转为目标指针类型必须判断返回值分配失败返回NULL直接使用会崩溃free仅释放堆内存不能释放栈指针释放后指针必须置NULL。三、C 动态内存关键字 / 操作符C 兼容 C 的malloc/free但推荐专用的new/delete、new[]/delete[]依赖 C 语法特性更安全、更面向对象。1.核心用法1单个对象// 申请int内存无初始化 int* p1 new int; // 申请初始化推荐 int* p2 new int(10); // 释放单个对象 delete p1; delete p2;2数组对象// 申请5个int的数组不初始化 int* arr new int[5]; // 释放数组必须用delete[] delete[] arr;3类对象new自动调用构造函数delete自动调用析构函数malloc/free无此功能class Test { public: Test() { cout 构造 endl; } ~Test() { cout 析构 endl; } }; Test* t new Test; // 调用构造 delete t; // 调用析构2.实现原理1内置类型如果申请的是内置类型的空间new和mallocdelete和free基本类似不同的地方是new/delete 申请和释放的是单个元素的空间new[] 和delete[] 申请的是连续空间而且new 在申请空间失败时会抛异常malloc会返回NULL。2自定义类型new的原理1. 调用operator new函数申请空间2. 在申请的空间上执行构造函数完成对象的构造delete的原理1. 在空间上执行析构函数完成对象中资源的清理工作2. 调用operator delete函数释放对象的空间new T[N]的原理1. 调用 operator new[] 函数在operator new[] 中实际调用 operator new 函数完成N个对象空间的申请2. 在申请的空间上执行N次构造函数delete[]的原理1. 在释放的对象空间上执行N次析构函数完成N个对象中资源的清理2. 调用 operator delete[] 释放空间实际在 operator delete[] 中调用 operator delete 来释放空间3.关键特性类型安全无需强转自动返回目标类型指针自动计算大小无需手动写sizeof失败处理分配失败抛出bad_alloc异常而非返回NULL严格配对new↔delete、new[]↔delete[]不可混用。operator new/deletenew 底层调用 operator new后者通过 malloc 申请空间失败时抛异常而非返回 NULLdelete 底层调用 operator delete最终通过 free 释放空间。定位 new在已分配的原始内存中显式调用构造函数用于内存池场景内存池分配的内存未初始化自定义类型需手动调用构造。四、区别栈区 vs 堆区特性栈区 (Stack)堆区 (Heap)增长方向向下高地址→低地址向上低地址→高地址管理方式系统自动分配 / 释放程序员手动分配 / 释放空间大小小固定上限大动态扩展分配速度极快较慢内存碎片无有分配连续性连续内存不连续内存生命周期函数作用域内手动控制全程C/C 动态内存--核心区别对比项malloc / freenew / delete本质C 标准库函数C关键字 / 操作符类型安全返回void*必须强转返回目标类型指针无需强转内存初始化不初始化可直接初始化内存大小手动指定字节数自动计算失败处理返回NULL抛出异常类对象不调用构造 / 析构自动调用构造 / 析构数组无专用语法new[]/delete[]严格配对五、常见错误动态内存的 bug 是程序崩溃、内存泄漏的主要原因核心错误野指针指针指向已释放 / 非法内存未初始化、free后未置空、越界内存泄漏申请的内存未释放堆内存耗尽忘记free/delete、指针丢失重复释放多次free/delete同一个指针直接崩溃不匹配释放new[]用delete、new用delete[]类对象会漏调用析构混用函数malloc搭配delete、new搭配free未定义行为释放栈内存用free释放栈区指针非法操作越界访问申请 n 个元素访问 n1 位置破坏内存realloc后直接使用原指针扩容失败返回NULL原指针失效不判断分配结果直接使用NULL指针内存交叉释放释放不属于自己的堆内存。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2463599.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!