C++的动态内存管理(new/delete的用法,malloc和new的区别,内存的具体分布)

张开发
2026/4/10 15:43:21 15 分钟阅读

分享文章

C++的动态内存管理(new/delete的用法,malloc和new的区别,内存的具体分布)
C的动态内存管理允许程序在运行是根据需要分配内存和释放内存主要通过new和delete运算符来完成。与静态内存分配相比动态内存分配更具有灵活性但它需要手动管理来避免内存泄漏。一·C/C中内存的具体分布先来了解一下内存的几个区域栈区向下增长非静态局部变量/函数参数/返回值即用即销毁的数据堆区向上增长动态申请的数据堆区的内存大小不固定可根据需要来进行内存的分配与释放静态区全局数据和静态数据static其在编译时就确定了变量的大小和内存地址具有固定的大小和位置代码区可执行代码和常量下面来看一道关于内存管理的面试题答案是C,C,C,A,A从左往右A,A,A,D,A,B前面提到静态区存放的是全局数据和静态数据所以很明显可以判断出前三个globalVarstaticGlobalVarstaticVar是存放在静态区数据段而localVar和num1都是在函数中临时创建的所以他们存放在栈区char2是一个数组也是在函数中被临时创建存放在栈区*char为首元素地址‘a’是这个数组的首元素而这个数组在栈区所以*char2存放在栈区pchar3是一个指针存放在栈区。注const并不会影响数据存储的区域可见这两块地址是挨着的所以const没有改变数据存储的区域*pchar3就是“a,b,c,d,/0”,存放在常量区ptr1和pchar3都是指针变量存放在栈区*ptr1就是动态开辟出来的应该存放在堆区2.填空题40544或84或8因为num1是整形数组但是只初始化了四个所以就是4*1040char2“abcd/0”char2里面存放的是字符串sizeofchar2就是计算该字符串的大小千万不能把/0给忘了。而strlen则是计算该字符串在‘/0’之前的字符串的大小pchar3和ptr1都是指针变量任何指针变量的大小都是4/8看是在32位还是在64位环境下同理strlenphar3也是计算/0之前的大小3.sizeof和strlen的区别sizeof() 是操作符不是函数它是用来计算对象或者类型创建的对象所占内存空间的大小strlen是一个函数计算字符串有效长度不包括/0二·C中的动态内存管理1new/delete操作内置类型C中的动态内存管理跟C语言的有些许差异因为C语言中的malloc/free使用起来比较麻烦并且不能对申请好的数据进行初始化所以在C中就做了相应的改进。使用new/delete来进行动态的申请内存。注new/delete是运算符而malloc/free是函数#includeiostream using namespace std; int main() { //C语言 int* p1 (int*)malloc(sizeof(int)); free(p1); int* p2 new int(10);//开辟一个初始化为10的空间 delete p2; int* p3 new int[10];//开辟10个int类型的空间 delete[]p3; return 0; }由此可见C通过new和delete操作符进行动态内存管理我们来看看C是如何使用new/delete来动态开辟空间的1.new操作符后直接跟类型2.要注意圆括号内是对该变量的初始化而方括号则是要开辟的数量3.申请和释放连续的空间使用new[]和 delete[]4.必须配对使用不能malloc/delete或者new/free长时间可能会导致内存泄露2new/delete操作自定义类型在申请自定义类型的空间时malloc只会申请空间并不会对其初始化而new则会去调用构造函数对该对象进行初始化delete则会对应的调用析构函数很显然malloc在开辟完空间后没有对p1进行初始化但是new和delete去调用了构造和析构函数注意malloc/free和new/delete必须配套使用不能随意使用时间长了可能会造成内存泄漏导致程序崩溃3malloc/free和new/delete的区别malloc/free和new/delete的共同点是都是从堆上申请空间并且需要用户手动释放。不同的地方是1. malloc和free是函数new和delete是操作符2. malloc申请的空间不会初始化new可以初始化3. malloc申请空间时需要手动计算空间大小并传递new只需在其后跟上空间的类型即可 如果是多个 对象[]中指定对象个数即可4. malloc的返回值为void*, 在使用时必须强转new不需要因为new后跟的是空间的类型5. malloc申请空间失败时返回的是NULL因此使用时必须判空new不需要但是new需要捕获异常6. 申请自定义类型对象时malloc/free只会开辟空间不会调用构造函数与析构函数而new在申请空间 后会调用构造函数完成对象的初始化delete在释放空间前会调用析构函数完成空间中资源的清理三.operator new和operator delete函数operator new和operator delete并不是直接的运算符重载而是C库里的全局函数。new在底层通过调用operator new来进行申请空间delete在底层通过调用operator delete来进行空间的释放下面来看一下operator new的用法int main () { A* p6 (A*)operator new (sizeof(A)); operator delete(p6); return 0; }由这个不难看出和malloc的用法大同小异但是他们还是有一定的区别就像上面这段代码并没有像malloc一样检查空间是否开辟成功因为 operator new开辟空间失败是会抛异常的其实operator new/operator delete被设计出来就是给new和delete服务的我们可以通过反汇编来查看反汇编中的call就是去调用子函数的由此可见在new的底层就是先去调用operator new去开辟空间然后调用构造函数区初始化其实原理上就是把new转换成调用operator new构造函数将delete转换成调用析构函数operator delete四.new和delete的实现原理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来释放空间

更多文章