C++之内存分配new与delete使用方式

发布时间:2026/8/26 7:59:16
C++之内存分配new与delete使用方式 C new 和 delete在C中new和delete是用于动态内存分配和释放的运算符。它们允许程序在运行时管理堆内存是实现动态数据结构如链表、树和灵活资源管理的基础。1. 基本语法new 运算符分配单个对象123Type* ptr newType;// 默认初始化内置类型值未定义Type* ptr newType(value);// 直接初始化Type* ptr newType{value};// 列表初始化C11起分配数组1Type* arr newType[size];// 分配包含size个元素的数组值初始化1Type* ptr newType();// 值初始化为0或默认构造函数delete 运算符释放单个对象1deleteptr;// 调用析构函数如有并释放内存释放数组1delete[] arr;// 释放数组内存需使用[]告知编译器释放多个对象2. 工作原理new 的执行步骤内存分配调用operator new或operator new[]用于数组分配原始内存。构造函数调用在分配的内存上调用对象的构造函数若为类类型。delete 的执行步骤析构函数调用对对象调用析构函数若为类类型。内存释放调用operator delete或operator delete[]释放内存。3. 深入理解 new 和 delete原始内存操作operator new和operator delete底层函数可被重载以自定义内存分配行为。1234void* operatornew(size_tsize);// 分配单个对象void* operatornew[](size_tsize);// 分配数组voidoperatordelete(void* ptr);// 释放单个对象voidoperatordelete[](void* ptr);// 释放数组示例1234void* raw_memory operatornew(sizeof(int));// 分配原始内存int* ptr static_castint*(raw_memory);// 转换为int指针*ptr 42;// 手动赋值operatordelete(ptr);// 释放内存不调用析构函数定位 newPlacement New在已分配的内存上构造对象1234void* buffer operatornew(sizeof(MyClass));// 分配原始内存MyClass* obj new(buffer) MyClass();// 在buffer上构造对象obj-~MyClass();// 显式调用析构函数operatordelete(buffer);// 释放内存4. 数组的动态分配分配与释放数组12345678910111213int* arr newint[10];// 分配10个int的数组delete[] arr;// 释放数组// 多维数组int** matrix newint*[5];// 分配5行for(inti 0; i 5; i) {matrix[i] newint[10];// 每行10列}// 释放for(inti 0; i 5; i) {delete[] matrix[i];}delete[] matrix;数组初始化1int* arr newint[5]{1, 2, 3, 4, 5};// C11起支持列表初始化在对数组进行动态分配时会自动在之前多分配一块空间用来储存所要开辟的空间个数以便将来用delete释放空间。5.new和delete的实现原理5.1 内置类型如果申请的是内置类型的空间new和mallocdelete和free基本类似不同的地方是new/delete申请和释放的是单个元素的空间new[]和delete[]申请的是连续空间而且new在申请空间失败时会抛异常malloc会返回NULL。5.2 自定义类型new的原理调用operator new函数申请空间在申请的空间上执行构造函数完成对象的构造delete的原理在空间上执行析构函数完成对象中资源的清理工作调用operator delete函数释放对象的空间new T[N]的原理调用operator new[]函数在operator new[]中实际调用operator new函数完成N个对象空间的申请在申请的空间上执行N次构造函数delete[]的原理在释放的对象空间上执行N次析构函数完成N个对象中资源的清理调用operator delete[]释放空间实际在operator delete[]中调用operator delete来释放空间6. 常见问题与注意事项内存泄漏原因忘记调用delete释放new分配的内存。示例1234voidleak() {int* ptr newint;// 分配内存// 未释放内存就返回}// 内存泄漏悬空指针原因释放内存后仍保留指向该内存的指针。示例123int* ptr newint;deleteptr;*ptr 10;// 悬空指针解引用未定义行为重复释放原因多次释放同一块内存。示例123int* ptr newint;deleteptr;deleteptr;// 重复释放未定义行为混用 delete 和 delete[]错误示例12int* arr newint[10];deletearr;// 错误应使用delete[]对于内置类型程序会崩溃而对于自定义类型程序不会崩溃。7. 自定义内存管理重载全局 operator new 和 operator delete12345678910void* operatornew(size_tsize) {void* p malloc(size);// 可添加内存分配日志、性能监控等returnp;}voidoperatordelete(void* p) noexcept {free(p);// 可添加内存释放日志等}类特定的内存管理123456789101112classMyClass {public:staticvoid* operatornew(size_tsize) {// 自定义分配逻辑return::operatornew(size);}staticvoidoperatordelete(void* p) noexcept {// 自定义释放逻辑::operatordelete(p);}};8. 与C语言内存管理的对比特性C new/deleteC语言 malloc/free类型安全自动推导类型无需强制转换需要显式转换如 (int*)malloc()构造/析构函数自动调用构造函数和析构函数不调用构造/析构函数初始化支持直接初始化和列表初始化仅分配内存不初始化值数组语法直接使用 new Type[size]需要计算总大小如 malloc(size*sizeof(Type))智能指针支持与标准库智能指针无缝配合需手动封装为智能指针malloc/free和new/delete的共同点是都是从堆上申请空间并且需要用户手动释放。不同的地方是malloc和free是函数new和delete是操作符malloc申请的空间不会初始化new可以初始化malloc申请空间时需要手动计算空间大小并传递new只需在其后跟上空间的类型即可 如果是多个对象[]中指定对象个数即可malloc的返回值为void*, 在使用时必须强转new不需要因为new后跟的是空间的类型malloc申请空间失败时返回的是NULL因此使用时必须判空new不需要但是new需要捕获异常申请自定义类型对象时malloc/free只会开辟空间不会调用构造函数与析构函数而new在申请空间后会调用构造函数完成对象的初始化delete在释放空间前会调用析构函数完成空间中资源的清理释放总结new/delete是C动态内存分配的核心机制适用于需要在运行时确定对象生命周期。实现动态数据结构如链表、树。优先使用智能指针现代C中std::unique_ptr和std::shared_ptr能有效避免内存泄漏提高代码安全性。谨慎手动管理内存必须确保new和delete配对使用避免悬空指针和重复释放