• 【C++】C++ new和malloc到底哪里不一样


    作者:李春港
    出处:https://www.cnblogs.com/lcgbk/p/14118782.html

    一、前言

    new和malloc的知识点,作为一个C++工程师是必须要了解清楚的,在面试中该知识点也是经常会被询问到的。所以在此文章,总结下new和malloc的区别到底在哪里。

    二、new和malloc两者的区别

    2.1 属性的区别

    • new/delete:这两个是C++中的关键字,若要使用,需要编译器支持;
    • malloc/free:这两个是库函数,若要使用则需要引入相应的头文件才可以正常使用。

    2.2 使用上的区别

    • malloc:申请空间需要显式填入申请内存的大小;
    • new:无需显式填入申请的内存大小,new会根据new的类型分配内存。

    实例:

    /** malloc/free用例 **/
    int  *ma  = (int*) malloc(4); 
    free(ma);
    
    /** new/delete用例 **/
    int *ne = new int(0);
    

    2.3 内存位置的区别

    • new:此操作符分配的内存空间是在自由存储区;
    • malloc:申请的内存是在堆空间。

    C/C++的内存通常分为:堆、栈、自由存储区、全局/静态存储区、常量存储区。可能除了自由存储区,其他的内存分布大家应该都比较熟悉。

    是C语言和操作系统的术语,堆是操作系统所维护的一块特殊内存,它提供了动态分配的功能,当运行程序调用malloc()时就会从中分配,调用free()归还内存。那什么是自由存储区呢?

    自由存储区 是C++中动态分配和释放对象的一个概念,通过new分配的内存区域可以称为自由存储区,通过delete释放归还内存。自由存储区可以是堆、全局/静态存储区等,具体是在哪个区,主要还是要看new的实现以及C++编译器默认new申请的内存是在哪里。但是基本上,很多C++编译器默认使用堆来实现自由存储,运算符new和delete内部默认是使用malloc和free的方式来被实现,说它在堆上也对,说它在自由存储区上也正确。因为在C++中new和delete符号是可以重载的,我们可以重新实现new的实现代码,可以让其分配的内存位置在静态存储区等。而malloc和free是C里的库函数,无法对其进行重载。

    2.4 返回类型的区别

    new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。而malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。所以在C++程序中使用new会比malloc安全可靠。

    2.5 分配失败情况的区别

    malloc分配内存失败时返回NULL,我们可以通过判断返回值可以得知是否分配成功;

    new内存分配失败时,会抛出bac_alloc异常,它不会返回NULL,分配失败时如果不捕捉异常,那么程序就会异常退出,我们可以通过异常捕捉的方式获取该异常,具体C++异常捕捉和处理的使用可以通过我往期【C++】 C++异常捕捉和处理的文章了解:https://www.cnblogs.com/lcgbk/p/13858425.html。

    2.6 定义对象系统调度过程的区别

    使用new操作符来分配对象内存时会经历三个步骤:

    1. 调用operator new 函数(对于数组是operator new[])分配一块足够的内存空间(通常底层默认使用malloc实现,除非程序员重载new符号)以便存储特定类型的对象;
    2. 编译器运行相应的构造函数以构造对象,并为其传入初值。
    3. 对象构造完成后,返回一个指向该对象的指针。

    使用delete操作符来释放对象内存时会经历两个步骤:

    1. 调用对象的析构函数。
    2. 编译器调用operator delete(或operator delete[])函数释放内存空间(通常底层默认使用free实现,除非程序员重载delete符号)。

    自己可以通过实例去验证下,此处就不展开例程了。

    2.7 扩张内存大小的区别

    • malloc:使用malloc分配内存后,发现内存不够用,那我们可以通过realloc函数来扩张内存大小,realloc会先判断当前申请的内存后面是否还有足够的内存空间进行扩张,如果有足够的空间,那么就会往后面继续申请空间,并返回原来的地址指针;否则realloc会在另外有足够大小的内存申请一块空间,并将当前内存空间里的内容拷贝到新的内存空间里,最后返回新的地址指针。
    • new:new没有扩张内存的机制。

    三、总结

    特征 new/delete malloc/free
    分配内存的位置 自由存储区
    内存分配失败 抛出异常 返回NULL
    分配内存的大小 编译器根据类型计算得出 显式指定字节数
    处理数组 有处理数组的new版本new[] 需要用户计算数组的大小后进行内存分配
    已分配内存的扩张 不支持 使用realloc完成
    分配内存时内存不足 可以指定处理函数或重新制定分配器 无法通过用户代码进行处理
    是否可以重载 可以 不可以
    构造函数与析构函数 调用 不调用
  • 相关阅读:
    原生小程序 自定义封装组件
    H5 es6 foreach使用
    原生小程序底部弹出层动画过渡
    vue 动画滑动
    H5 textarea高度自适应
    关于Java日期加减,并且比较大小的方法
    activiti多实例如何配置
    常用类——Date——Calendar
    常用类-String
    Wrapper-装箱和拆箱
  • 原文地址:https://www.cnblogs.com/lcgbk/p/14118782.html
Copyright © 2020-2023  润新知