1、属性
new/delete是C++的运算符,malloc/free是标准库函数
2、参数
new运算符根据数据类型,自动决定其大小,不使用sizeof运算符,而malloc要指定分配存储空间的大小。
3、返回类型
new返回指向此类型的指针,不用进行强制类型转换。故new是符合类型安全性的操作符。malloc返回指向void *类型的指针,需要进行强制类型转换。
4、初始化
new是一个分配内存并进行初始化的过程,例如,cha *p = new char(‘a');而malloc()仅仅是一个函数,没有初始化的过程,需要编码人员手动初始化。
5、分配失败
malloc分配内存失败时返回NULL,new内存分配失败时,有两种情况:
1)抛出bad_alloc异常来报告分配失败;
2)返回空指针,而不会抛出异常。
首先,c++是在c语言的基础之上发展而来,而且c++发明时是想尽可能的与c语言兼容。而c语言是一种没有异常机制的语言,所以c++应该会提供一种没有异常机制的new分配内存失败报告机制;(确实是如此,早期的c++还没有加入异常机制),其次在返回空指针的实现过程中,c++采用的是malloc/calloc 等分配内存的函数,该类函数不会抛出异常,但是在分配内存失败时会返回“空指针”。最后,对于标准的c++,有着比较完善的异常处理机制,所以对于出现异常时,会抛出响应的异常。对于new分配失败时,系统会抛出bad_alloc异常。
所以具体是那种情况,看编译器对标准c++的支持情况。
6、自定义类型(类等)
对于自定义类型,new会先调用operator new函数,申请足够的内存(通常底层使用malloc实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型指针。delete先调用析构函数,然后调用operator delete函数释放内存(通常底层使用free实现)。
malloc/free是库函数,只能动态的申请和释放内存,无法强制要求其做自定义类型对象构造和析构工作。
7、重载
C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回此地址。而malloc不允许重载。
8、 内存区域
new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。自由存储区不等于堆,如上所述,布局new就可以不位于堆中。
自由存储区是否可以是堆?这取决于operate new 的实现细节。自由存储区不仅仅可以是堆,还可以是静态存储区,这取决于operate new 在哪里为对象分配内存。
十个区别:
特征 | new/delete | malloc/free |
---|---|---|
分配内存的位置 | 自由存储区 | 堆 |
内存分配成功返回 | 完整类型指针 | void* |
内存分配失败返回值 | 默认抛出异常 | 返回NULL |
分配内存的大小 | 由编译器根据类型计算得出 | 必须显式指定字节数 |
处理数组 | 有处理数组的new版本new[] | 需要用户计算数组的大小后进行内存分配 |
已分配内存的扩充 | 无法直观地处理 | 使用realloc简单完成 |
是否相互调用 | 可以,看具体的operator new/delete实现 | 不可调用new |
分配内存时内存不足 | 客户能够指定处理函数或重新制定分配器 | 无法通过用户代码进行处理 |
函数重载 | 允许 | 不允许 |
构造函数与析构函数 | 调用 | 不调用 |
a)malloc 可以通过realloc重新分配内存大小
void *raealloc(void *ptr,size_t size)
void *ptr表示之前malloc分配内存空间的首地址,size是新的内存大小。注意新分配大小不能比malloc所申请的小,否则会造成数据丢失。
b)在使用delete后,注意将指针置为NULL,否则会形成悬垂指针(指针所指内存已被释放,仍指向该内存),造成错误
这是因为delete后,虽然内存释放的了,但是指针所指向的地址仍未改变,只是内容被清除。后续代码任然可以调用。
c)new与delete,new a[ ]与delete [ ] a成对使用,除了(当new的内存空间分配给没有显式定义给、析构函数类的指针,可以使用delete[ ]释放)
PS:在C++中,内存区分为5个区,分别是堆、栈、自由存储区、全局/静态存储区、常量存储区;
在C中,C内存区分为堆、栈、全局/静态存储区、常量存储区;