malloc/free和new/delete之间关系和差异
相同点:
都可用于申请动态内存和释放内存
不同点:
(1)操作对象不同
malloc/free是C++/c语言的标准库函数,new/delete是c++的运算符,对于非内部数据类型的对象而言,只有malloc、free是无法满足动态对象的要求的。因为对象在创建的时候会自动调用构造函数,对象消亡时会自动调用析构函数。因为malloc/free是库函数而不是运算符,不在编译器控制的范围内,不能够执行构造函和析构函数
(2)用法不同
函数malloc 的原型如下:
void*malloc(size_t size)
用malloc申请一块长度为n的整数类型的空间,代码如下
int p = (int)malloc(sizeof(int)*n);
注意:
<1>. malloc返回值是void* ,岁哟调用时要进行显示的类型转换,讲void* 转换成所需要的类型
<2>.malloc函数本身并不识别要申请的内存是什么类型,只关心内存的总字节数
函数free的原型:
void free(void* memblock)
为什么free函数不像malloc函数那样复杂呢?这是因为指针p 的类型以及他所指向的内存的容量都是事先知道的,free(p)才可以正确的释放p,如果p是NULL,free对p乌云操作多少次都不会出现问题,而如果p不是NULL,那么free进行两次就会出现错误,就是已经释放的空间连续释放,就会出现问题
new、delete
运算符new 使用起来要比函数malloc 简单得多,例如:
int p1 = (int )malloc(sizeof(int) * length);
int *p2 = new int[length];
这是因为new 内置了sizeof、类型转换和类型安全检查功能。对于非内部数据类型的对象而言,new 在创建动态对象的同时完成了初始化工作。
delete是与new成对出现的,new/delete new[]/delete[] 注意一定要成对使用
1、本质区别
malloc/free是C/C++语言的标准库函数,new/delete是C++的运算符。
对于用户自定义的对象而言,用maloc/free无法满足动态管理对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。因此C++需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。
2、联系:
既然new/delete的功能完全覆盖了malloc/free,为什么C++还保留malloc/free呢?因为C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。如果用free释放“new创建的动态对象”,那么该对象因无法执行析构函数而可能导致程序出错。如果用delete释放“malloc申请的动态内存”,理论上讲程序不会出错,但是该程序的可读性很差。所以new/delete、malloc/free必须配对使用。
剖析new/delete、new[]/delete[]到底做了些什么事情。
不管是new还是new[] 都调用了operator new函数,在operator new函数中,又调用了malloc函数。
当然new[] 调用了operator new[] 而operator new[] 又调用了operator new函数。
在底层实现中,new就是用malloc函数来开辟空间的。
实现NEW_ARRAY/DELETE_ARRAY宏,模拟new[]/delete[]申请和释放数组。
#define NEW_ARRAY(PTR,TYPE,N)
do
{PTR = (TYPE*)operator new(sizeof(TYPE)*N+4)
(*(int*)PTR) = N
for(size_t i = 0;i<N;i++)
new (PTR+i)TYPE;
}while(false);
//为什么在申请空间的时候要多申请四个字节呢?这是因为需要用来记录对象的个数,可以知道在析构的是后要调用几次
//析构函数
#define DELETE_ARRAY(PTR,TYPE)
do{int N = *((int*)PTR-1) //这里取出保存的对象的个数
for(size_t i=0;i<N;i++)
{PTR[i].~TYPE();
PTR = (TYPE*)((char*)PTR-4);
operator delete(PTR); }
}while(false);
//注意:在用宏实现的收,一定要加上续行符。