最近在复习C++的时候遇到了这个问题,于是把它记录下来。malloc和new的区别可以总结为8点
出身不同
malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符
使用的空间不同
new操作符从自由存储区上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。
所谓的自由存储区,是C++中通过new与delete动态分配和释放对象的抽象概念。堆与自由存储区并不等价。缺省的全局运算符new和delete也许会按照malloc和free的方式来被实现,这时由new运算符分配的对象使用空间在堆上。但程序员也可以通过重载操作符,改用其他内存来实现自由存储,比如在静态存储区的全局变量池。
返回类型的安全性不同
malloc返回void*,需要强制转换类型。
new返回对象类型的指针,类型严格与对象匹配。在分配的时候,首先是调用了operator new/new[](operator new/new[]函数和new表达式是两个东西)operator new/new[]返回的是一个void*类型的指针,指向一块原始空间,之后new再调用对象的构造函数,最终,再将void*指针类型转换成对象的类型的指针返回。
分配失败的返回值不同
new:bac_alloc异常
(我们也可以指定使用不抛出异常的new版本,如:int* p = new(nothorw) int;传递给operator new 一个nothorw对象,该对象定义在头文件。若分配失败,返回一个空指针)
malloc:NULL(即数值上为0)
C++的新手可能会有这样的一个错误习惯:
int * num = new int();
if(num == NULL)
{
...
}
else
{
...
}
实际上这样做一点意义也没有,它不会帮助new检查是否分配空间失败,因为new不会返回NULL,如果程序能够执行到if语句说明内存分配成功,否则应该抛出bac_alloc异常。 正确的做法应该是使用异常机制:
try
{
int *a = new int();
}
catch (bad_alloc)
{
...
}
是否需要指定内存大小
new无须指定内存块大小,编译器自行计算,malloc需要。 比如动态分配一个数组:
int* p1 = (int*)malloc(sizeof(int)*length);
int* p2 = new int[length];
是否调用构造函数/析构函数
对于非内部数据类型的对象而言,光用malloc/free无法满足动态对象的要求。因为对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。
使用new操作符来分配对象内存会经历三个步骤:
- 调用operator new 函数(对于数组是operator new[]),分配一块足够大的未命名的内存空间
- 编译器调用对象相应的构造函数以构造对象并传入初值。
- 对象构造完毕,返回一个指向该对象的指针
使用new操作符来分配对象内存会经历两个步骤:
- 调用对象的析构函数以销毁对象
- 编译器调用operator delete函数(对于数组是operator delete[])释放内存空间
对数组的处理
c++提供了new[]与delete[]来专门处理数组类型
malloc需要用户计算数组的大小后进行内存分配。malloc只是分配空间,不作其他的工作。
实现方式
operator new /operator delete的实现基于malloc
可否被重载
new和delete可以被重载,malloc和free不可以