一、C语言中的动态内存管理方式
malloc/calloc/realloc三种开辟内存的方式
1.malloc函数原型 void* malloc(size_t size)
需要动态开辟内存空间时调用malloc函数,可以在堆上开辟出一块连续的内存空间,并且返回指向这一块内存的指针。来满足程序的需求。
1.2.在用malloc函数开辟空间时应注意:
- 申请开辟空间成功,则会返回一个指向这块内存的指针
- 如果申请开辟空间失败,就会返回一个NULL指针,所以malloc开辟的空间一定要检查是否开辟成功
- 由于malloc的开辟空间返回值类型是void* 开辟的空间类型需要我们自己根据需要来给定。
- 当size大小是0时开辟空间的大小是未定义行为,具体大小有编译器决定VS2017默认分配一个类型空间的大小
2.C语言另外一个可以在堆上开辟空间的函数即calloc
2.1函数原型:void* calloc(size_t Num, size_t size)
2.2其中Num是块个数,size是一块所占字节大小
2.3calloc函数就是为Num个大小为size的元素开辟一块空间
calloc和malloc的区别就是:calloc在开辟空间后,会初始化空间的每个字节为0
3.C语言中第三种realloc函数将更加灵活地开辟空间
3.1realloc函数原型: void* realloc(void* ptr, size_t size)
3.2 realloc开辟空间,当申请的空间大了或者小了都会及时作出调整出一块合适的空间。
3.3ptr要调整的内存的地址的指针,size调整后的大小
3.4返回值为调整后的返回内存空间的起始地址。在申请的空间大了时直接缩小空间即可,不用搬移数据。在申请空间小时往大的调整过程总有两种情况:①先查看原由空间后面的可用空间够不够,如果够,就不用搬移数据直接追加空间,②当后面空间不够时就需要重新开辟一块内存空间,再将数据搬移过去。
在开辟了堆上的内存之后一定要及时释放防止造成内存泄漏。
二、说完C语言中的动态开辟空间问题在说C++中的动态内存管理
在C++中当然也可以通过C语言中的函数来进行动态内存管理,但有时会比较麻烦,所以C++有自己的动态管理内存的方式
用new和delete操作符来申请和释放空间
在C++中通过一个new来为对象开辟空间,它会调用构造函数初始化空间,通过delete释放空间前会调用析构函数进行对象中资源的清理工作。
1new Object与delete Object
在创建一个对象时会经历两步:
第一步会在底层会先调用operator new来申请一块空间,之后再调用构造函数来对对象进行初始化。operator new申请空间有两种可能:①:一种是申请成功返回空间首地址,②:再就是申请失败,在申请失败时就需要用户来给出解决办法。如果用户给定解决办法。就会检测到显示提供,就循环申请空间,每次将占据内存且不使用的对象清理调,直到申请成功,如果没有提供就直接抛出异常bad_alloc。 operator new也是通过malloc来创建空间的。
第二步当空间创建好之后就调用构造函数初始化对象
同样在销毁一个对象时也会经历两步:
第一步执行delete Object 时会先调用析构函数对对象的资源进行清理。
第二步调用operator delete来销毁对象,它实际是通过free来释放内存
三、一组对象的创建与销毁历程
new object[N]
创建一组对象时第一步先调用void* operator new[](count=sizeof(Object)*N+4),直接调用operator new(count)循环调用malloc来创建空间并且都判断申请是否成功以及失败时解决办法。在调用operator new[]中实际还是调用的operator new
第二步先将前四个字节写上对象的个数,之后调用构造函数构造N个Object对象。
销毁一组对象时:delete[] object
第一步:先调用析构函数来释放N个对象的资源,清理对象的资源是倒着进行清理这是由于对象的生命周期不一样
第二步:调用void operator delete[](void* ptr)实际也是调用void operator delete(void* ptr)来释放对象所在空间。最终是通过free(ptr)。
四、malloc/free与new/delete的区别:
①:malloc和free是函数,new和delete是操作符
②:malloc申请空间失败会返回NULL必须判空,二new不需要,但是需要捕捉异常
③:malloc不会对申请的空间进行初始化,而new会初始化
④:malloc需要明确知道申请空间的大小,而new后只跟上类型即可
⑤:malloc申请空间返回值必须进行强转,而new不用,因为它就跟着类型
⑥:申请自定义对象空间时,new和delete会分别调构造函数和析构函数。而malloc和free不会
造成这么多区别的原因就是malloc和free种种不太合适的问题,new和delete是在malloc和free上的一层封装。这和引用与指针的区别原因有很大的类似情况。
最后一点,动态申请空间不一定要释放空间,因为它不一定在堆上开辟空间也可能在栈上就比如:alloca函数下一篇将介绍此函数。
珍&源码