这个问题堪称经典。如果你是面试官,我建议你把这个问题作为你面试求职者的必选题目之一。如果你是求职者,我会建议你读懂和熟透这个题目涉及到的知识点。这个问题涉及到了C和C++中最经典的部分,可能也是C和C++的交汇。

一些刚毕业的学生如果没有经验可能很难深有体会,大都数是强背。而工作多年的人深有体会是因为一个入门了,一个是吃过亏了,然后对编程和语言本身都有很大的升华。如果工作多年还不能回答此问题的,我觉得不算是很好的程序员。我认为可以从内存区域,重载,自定义类型,分配成功,返回类型,参数,属性等方面来聊一聊。

内存区域

如果能从内存回答的话,基本可以判定这个人是优秀的。很多人都会觉得new和malloc都在堆上,事实上不太准确的。

new操作符从自由存储区上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。

而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。自由存储区不等于堆,如上所述,布局new就可以不位于堆中。

重载

C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回此地址。

而malloc不允许重载,这条要记得,malloc不能重载。new重载,可以有多个构造函数。

自定义类型

new会先调用operator new函数,申请足够的内存(通常底层使用malloc实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型指针。delete先调用析构函数,然后调用operator delete函数释放内存(通常底层使用free实现)。

malloc/free是库函数,只能动态的申请和释放内存,无法强制要求其做自定义类型对象构造和析构工作。

分配失败

new内存分配失败时,会抛出bac_alloc异常。优秀的程序员会在使用的时候去判断内存分配是否成功,很多人new完是不作判断的,所以我的看法是你如果非常有自信,不然还是要一定的判断语句或者日志log便于追踪后续。

malloc分配内存失败时返回NULL。

返回类型

new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符,这里特别提到类的构造函数,构造函数是没有返回类型的,是不能返回的。

而malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。

参数

使用new操作符申请内存分配时无须指定内存块的大小,最常见的就是类的实例化。只要new然后传参即可。编译器会根据类型信息自行计算。

而malloc则需要显式地指出所需内存的尺寸,malloc很多新手都是给的内存尺寸不够多。记得以前有个C项目代码,有个新手不断用数组造成栈溢出,而另外一个个人不断用malloc分配内存也造成常见的crash。

属性

new对应delete,是C++关键字,需要编译器支持。malloc对应free是库函数,需要头文件支持。在编程代码中,一定要记得关键字对应匹配,不能分配内存不释放或者分配不成功就去释放。

我面试过深信服,字节跳动,迅雷等互联网公司,无一例外的考了这道题目。很多时候面试官都是当成一道基础题目来考你,但凡你能够用内存上或者平日里的一些心得来回答,我觉得都会让你脱颖而出。

打开网易新闻 查看精彩图片