1.申请内存的所在位置
new是在自由存储区上申请内存;malloc是在堆上申请内存。
凡是由new操作符申请的内存空间,该内存就是自由存储区,这是c++里的一个概念;而堆是操作系统里的一个概念,是操作系统维护的一块特殊内存,用于程序的动态存储。
malloc是从堆上分配内存,用free释放已分配的内存;而new能否在堆上分配内存,这取决与new的实现细节,具体来说,new可以在堆上分配内存,也可以在静态存储区上分配。
下面这段代码,说明了new可以在静态存储区上分配内存。
#include<iostream>
#include<new>
using namespace std;
const int buf(512);
int N(5);
int a[buf] = { 1 };
int main()
{
cout << a[0] << endl;
int *p1, *p2;
p1 = new int[N];
p2 = new (a)int[N]; //分配的内存从a开始,连续N个存储单元
cout << &a[0] << endl;
*p2 = 5;
for (int i = 0; i < N; i++)
{
cout << &p2[i] << endl;
}
cout << a[0] << endl;
}
2.返回类型的安全性不同
new操作符内存分配成功时,返回的是对象类型的指针,类型与对象严格匹配,无需进行强制类型转换;而malloc内存分配成功返回的是void *,需要进行强制类型转换才能变成我们需要的类型。
3.内存分配失败时的返回值不同
new分配内存失败时,返回的是bac_alloc异常,不会返回NULL;而malloc分配内存失败时,返回NULL。
在c语言里,通常用返回结果是不是NULL来判断内存是否分配成功;但是到了c++里,则不能,应为new失败并不能返回NULL,所以在c++里,应该使用异常机制,即try-catch结构。
4.是否需要指定内存的大小
new在分配内存时,不要指定分配内存的大小,编译器会根据类型信息计算;而malloc则要显式的指出所需的内存。
5.是否调用构造/析构函数
new在分配内存时会经历三个步骤:
- 调用operator new函数,分配一块足够大的,原始的,未命名的内存以存储特定类型的对象;
- 编译器运行相应的构造函数来构造对象,并传入初值;
- 对象构造完成后,返回一个指向该类型的指针。
delete释放内存会经历两个步骤:
- 调用对象的析构函数
- 编译器调用operator delete函数释放内存空间。
new给对象分配内存空间时,会调用对象类型的构造函数,而malloc则不会调用构造函数。这就造成了,在c++里,new是更加适用的,因为在涉及到类有构造/析构函数时,new的效果更好。
下面这段程序说明了new调用了类的构造函数,类成员a被初始化为1;而malloc没有嗲用构造函数,其值不为1。
#include "stdafx.h"
#include<iostream>
using namespace std;
class A
{
public:
A() :a(1), b(1.11)
{
}
int a;
double b;
};
int main()
{
A *p1 = new A;
A *p2 = (A*)malloc(sizeof(A));
cout << p1->a<<endl;
cout << p2->a<<endl;
}
调试结果如下:
6.对数组的处理不同
c++提供了new[]和delete[]来专门处理数组;而malloc则不知道是不是数组,反正就是分配一块内存,所以要用malloc动态分配数组内存时,还是要手动给定数组所需内存的大小。
7.new和malloc是否可以相互调用
operator new和operator delete可以基于malloc来实现;但malloc的实现不可以去调用malloc。
8.是否可以被重载
mew和delete可以被重载,而malloc/free不允许被重载。
9.是否能够直观的重新分配内存
在malloc分配内存之后,如果发现内存不足,可以适用realloc函数进行内存的重新分配。realloc重新分配内存的原理如下:realloc会判断当前指针所指的内存是否有连续的空间,如果有,则原地扩大分配的内存地址,并返回原来地址指针;如果空间不够,先按照新指定的大小分配空间,并将原有数据从头到尾拷贝到新分配的内存空间,而后释放原来的内存区域。
new则没有这样直观的配套设施来扩充内存。
10.内存分配不足时相应的处理不同
new在内存分配不足时,会抛出异常,那么在抛出异常之后,它会先调用一个用户指定的错误处理函数,即new_handler。
而malloc,客户并不能够去编程决定内存不足时要干什么事,智能看着malloc返回NULL。