1:总结并剖析malloc/free和new/delete之间关系和差异。
C语言使用malloc/calloc/realloc/realloc进行动态内存管理。
void *malloc(size_t size):该函数分配SIZE个字节,并返回了指向这块内存的指针。如果分配失败,则返回一个空指针(Null)
void free(void *memblock):该函数是将之前用Malloc分配的空间还给程序或者是操作系统,也就是释放了这块内存,让它重新得到自由
C++ 通过 new和delete动态管理内存。
new和delete动态管理对象
new[]和delete[]动态管理对象数
new/delete是可以重载的,而重载之后,就成为了函数
注意malloc/free、new/delete、new[]/delete[]一定要匹配使用,否则可能出现内存泄漏甚至崩溃的问题
小结
1、两组函数都负责动态内存管理
2、malloc/free是C/C++标准库的函数,而new/delete是C++操作符。
3、malloc/free只负责动态分配空间/释放空间,而new/delete还会调用构造函数和析构函数进行初始化和清理
4、malloc/free需要手动计算类型大小且返回值为void*,new/dellete可自己计算类型大小,返回对应类型指针。
2:剖析new/delete、new[]/delete[]到底做了些什么事情。
在使用new开辟一个AA大小的空间时,我们打个断点,按F11逐语句与F10逐过程就会跳到构造函数内部,并且在申请完毕后也输出了构造函数内部的内容
在使用delete释放时,在逐语句执行,最后我们发现可以输出析构函数内部的语句。
new/delete的调用过程
new[]/delete[];
我们通过内存可以看出在我们动态申请多个自定义类型大小的空间时,申请空间首地址之前的四个字节中存放了我们所申请给定类型的个数,以
便在接下来的析构函数中使用
3:实现NEW_ARRAY/DELETE_ARRAY宏,模拟new[]/delete[]申请和释放数组。
模拟实现new[count]
#define NEW_ARR(PTR,TYPE,N) \
do \
{ \
PTR = (TYPE*)operator new(sizeof(TYPE)*N + 4); \ //额外开辟4个字节存放对象个数
*(int*)PTR = N; \
PTR = (TYPE*)((INT*)PTR + 1); \
for (int i = 0; i < N;i++) \
new(PTR + i)TYPE; \ //定位new表达式是在已经分配的空间中调用析构函数初始化一个对象
}while (false);
模拟实现delete[]
#define DELETE_ARR(PTR,TYPE) \
do \
{ \
int n = *((int*)PTR - 1); \ //找出ptr前4个字节中存放的N
PTR = (TYPE*)PTR; \
for (int i = 0; i < n;i++) \ //再调用N次析构函数
PTR [i].~TYPE(); \
PTR = (TYPE*)((int*)PTR -1); \ //释放开辟的总空间
operator delete(PTR); \
}while (false);