new和malloc的区别
属性的区别
new是C++中的关键字,若要使用,需要编译器支持;
malloc是库函数,若要使用则需要引入相应的头文件才可以正常使用。
使用上的区别
malloc:申请空间需要指定填入申请内存的大小;
new:无需指定申请的内存大小,new会根据new的类型分配内存。
内存位置的区别
new:此操作符分配的内存空间是在自由存储区;
malloc:申请的内存是在堆空间。
返回类型的区别
new: 返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。
malloc: 返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。
在C++程序中使用new会比malloc安全可靠。
分配失败情况的区别
new: 内存分配失败时,会抛出bac_alloc异常,它不会返回NULL,分配失败时如果不捕捉异常,那么程序就会异常退出,我们可以通过异常捕捉的方式获取该异常。
malloc: 内存分配失败时返回NULL,我们可以通过判断返回值可以得知是否分配成功;
构造函数是否被调用的区别
new:
使用new操作符来分配对象内存时会经历三个步骤:
-
调用operator new 函数(对于数组是operator new[])分配一块足够的内存(通常底层默认使用malloc实现,除非程序员重载new符号)以便存储特定类型的对象;
-
编译器运行相应的构造函数以构造对象,并为其传入初值。
-
对象构造完成后,返回一个指向该对象的指针。
使用delete操作符来释放对象内存时会经历两个步骤:
-
调用对象的析构函数。
-
编译器调用operator delete(或operator delete[ ])函数释放内存空间(通常底层默认使用free实现,除非程序员重载delete符号)。
malloc:
默认构造函数不被调用。
扩张内存大小的区别
new:new没有扩张内存的机制。
malloc:使用malloc分配内存后,发现内存不够用,那我们可以通过realloc函数来扩张内存大小。
realloc会先判断当前申请的内存后面是否还有足够的内存空间进行扩张,如果有足够的空间,那么就会往后面继续申请空间,并返回原来的地址指针;否则realloc会在另外有足够大小的内存申请一块空间,并将当前内存空间里的内容拷贝到新的内存空间里,最后返回新的地址指针。
对数组处理的区别
new:
C++提供了new[ ]与delete[ ]来专门处理数组类型:
A * ptr = new A[10];//分配10个A对象
使用new[ ]分配的内存必须使用delete[ ]进行释放:
delete [] ptr;
new对数组的支持体现在它会分别调用构造函数函数初始化每一个数组元素,释放对象时为每个对象调用析构函数。注意delete[ ]要与new[ ]配套使用,不然会找出数组对象部分释放的现象,造成内存泄漏。
malloc:
至于malloc,它并知道你在这块内存上要放的数组还是啥别的东西,反正它就给你一块原始的内存,在给你个内存的地址就完事。所以如果要动态分配一个数组的内存,还需要我们手动自定数组的大小:
int * ptr = (int *) malloc( sizeof(int) );//分配一个10个int元素的数组
重载的区别
new:
C++允许重载new/delete操作符,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回此地址。
malloc:不允许重载。
new与malloc是否可以相互调用
operator new /operator delete的实现可以基于malloc,而malloc的实现不可以去调用new
补充知识
栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。
堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。
自由存储区 — C++中动态分配和释放对象的一个概念,通过new分配的内存区域可以称为自由存储区,通过delete释放归还内存。
自由存储区可以是堆、全局/静态存储区等,具体是在哪个区,主要还是要看new的实现以及C++编译器默认new申请的内存是在哪里。
文章参考:
https://zhuanlan.zhihu.com/p/338489910
https://blog.csdn.net/Linux_ever/article/details/50533149