zoukankan      html  css  js  c++  java
  • 【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完成
    分配内存时内存不足 可以指定处理函数或重新制定分配器 无法通过用户代码进行处理
    是否可以重载 可以 不可以
    构造函数与析构函数 调用 不调用
  • 相关阅读:
    团队项目-第一阶段冲刺7
    团队项目-第一阶段冲刺6
    Spring Boot 揭秘与实战(七) 实用技术篇
    Spring Boot 揭秘与实战(七) 实用技术篇
    Spring Boot 揭秘与实战(六) 消息队列篇
    Spring Boot 揭秘与实战(五) 服务器篇
    Spring Boot 揭秘与实战(五) 服务器篇
    Spring Boot 揭秘与实战(五) 服务器篇
    Spring Boot 揭秘与实战(五) 服务器篇
    Spring Boot 揭秘与实战(四) 配置文件篇
  • 原文地址:https://www.cnblogs.com/lcgbk/p/14118782.html
Copyright © 2011-2022 走看看