【面试题】---new和malloc的区别

引言

看过很多C/C++的基础面经不难发现很多常考的问题,new和malloc的区别这一经典面试题,相信很多人都在面试中遇到过,但是很难答的全面,因此想有详细完整的答案,在查阅资料以及自我见解总结之后,今天我在这里整理了一下,以便日后复习使用。

一、两者实现原理(重要)

  • new的实现原理:new的底层就是malloc,他会先调用malloc申请内存空间,然后再调用析构函数释放内存。
  • malloc的实现原理:malloc函数的实质体现在,它有一个将可用的内存块连接为一个长长的列表的所谓空闲链表的功能。调用malloc函数时,它沿连接表寻找一个大到足以满足用户请求所需要的内存块。然后,将该内存块一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到连接表上。调用free函数时,它将用户释放的内存块连接到空闲链上。到最后,空闲链会被切成很多的小内存片段,如果这时用户申请一个大的内存片段,那么空闲链上可能没有可以满足用户要求的片段了。这都是是为了减少内存碎片和系统调用的开销,malloc采用了内存池的方式,先申请大块内存作为堆区,然后将堆区分为多个内存块,以块作为内存管理的基本单位。同时malloc采用显示链表结构来管理所有空闲块,即使用一个双向链表将空闲链表连接起来,每一个空闲块记录了一个连续、未分配的地址。
    当内存进行分配时,malloc会通过隐式链表遍历所有的空闲板块,选择满足要求的块进行分配,当进行内存合并时,malloc采用边界标记法,根据每个块前后块是否已经分配来决定是否进行块合并。
    malloc在申请内存时,一般会通过brk或者mmap系统调用进行申请。其中当申请内存小于128K时,会使用系统函数brk在堆区中分配;而当申请内存大于128K时,会使用系统函数mmap在映射区分配。

二、两者区别(必看重重重点)

  • 1.参数 使用new操作符申请内存分配时无需指定内存块的大小,编译器会根据其信息自行计算,且需要用户自己初始化。而malloc则需要显示地指出所需内存的大小,会自行初始化。
  • 2.属性 new/delete是C++的关键字,需要编译器支持。 malloc/free是库函数,需要头文件的支持。
  • 3.返回类型 new操作符内存分配成功时,返回的类型是指针,类型严格与对象匹配,无需转换,所以new是符合类型的安全操作符。
    而malloc返回的是void*,需要通过强制类型转换,强void*转换成我们需要的类型。
  • 4.重载 C++允许重载new/delete操作符,在布局new的就不需要为对象分配内存,而是指定一个地址作为内存起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回地址。而malloc不允许重载。
//这些版本可能抛出异常
void * operator new(size_t);
void * operator new[](size_t);
void * operator delete (void * )noexcept;
void * operator delete[](void *0)noexcept;
//这些版本承诺不抛出异常
void * operator new(size_t ,nothrow_t&) noexcept;
void * operator new[](size_t, nothrow_t& );
void * operator delete (void *,nothrow_t& )noexcept;
void * operator delete[](void *0,nothrow_t& )noexcept;
  • 5.自定义类型 new会先调用operator new函数,申请足够大的内存(底层用malloc实现)。然后调用类型的构造函数,初始化成员变量最后返回自定义类型指针。delete先调用析构函数,然后调用operator
    delete函数释放内存(底层还是free函数实现的)
  • 6.分配失败 new内存分配失败时,会抛异常,即出现bac_alloc现象异常。 malloc分配内存失败时返回NULL
  • 7.对数组的处理 C++提供了new[]与delete[]来专门处理数组类型:
A * ptr = new A[10];//分配10个A对象

使用new[]分配的内存必须使用delete[]进行释放:

delete [] ptr;
  • new对数组的支持体现在它会分别调用构造函数初始化每一个数组元素,释放对象时为每个对象调用析构函数。注意delete[]要与new[]配套使用,不然会找出数组对象部分释放的现象,造成内存泄漏。
  • 至于malloc,它并不知道你在这块内存上要放的数组还是啥别的东西,反正它就给你一块原始的内存,在给你个内存的地址就完事。所以如果要动态分配一个数组的内存,还需要我们手动自定数组的大小:
int * ptr = (int *) malloc( sizeof(int) );//分配一个10个int元素的数组
  • 8.内存区域 new操作符从自由存储区上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区,而堆是操作系统中的术语,是操作系统所维护的一块特殊区域内存,用于程序的内存动态分配,C语言使用的malloc从堆上分配内存,使用free释放已经分配的内存。自由存储区不等于堆,所以new不可能位于堆上。
new int(10); //在堆上开辟了一个4字节的int整型内存,初始值是10
new int[10](); //在堆上开辟了一个包含10个整型元素的数组,初始值都为0

malloc(100); //在堆上开辟了100个字节的内存
  • 注意点: delete和free被调用后,内存不会立即回收,指针也不会指向空,delete或free仅仅是告诉操作系统,这一块内存被释放了,可以用作其他用途。但是由于没有重新对这块内存进行写操作,所以内存中的变量数值并没有发生变化,这时候就会出现野指针的情况。因此,释放完内存后,应该把指针指向NULL。

总结如图

在这里插入图片描述

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

L19002S

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值