new-delete-malloc-free关系总结

写在前面的话

面试中可以这样简单的回答

  1. new/delete会调用对象的构造/析构函数, 而malloc/free只会释放内存;
  2. malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符;
  3. 它们都可用于申请动态内存和释放内存;
  4. 对于非内部数据类型的对象(自己声明的类对象)而言,光用maloc/free无法满足动态对象的要求(为什么?);
  5. 对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数;
  6. 由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free;
    • malloc一个对象会发生什么事呢? malloc返回的是指向一块内存区域的原始指针, 需要进行强制转换, 而且没有构造对象, 里面的东西还是原来的样子;
  7. 因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete;
  8. 注意new/delete不是库函数, 他们是像(=等于符号)的一种特殊的操作符

或者可以这样简单的回答

  1. new是从自由存储区上分配内存, malloc是从堆上分配内存, 弄明白自由存储区和堆的概念!

    • 堆是操作系统维护的一块特殊内存;
    • 自由存储区时new/delete动态分配和释放对象的抽象概念, 通过new来申请的内存区域可以成为自由存储区;
    • 堆与自由存储区并不等价, 因为new可以通过运算符重载, 改用其他内存来实现自由存储区;
    • 简单的来讲, 就是自由存储区不仅仅是堆, 它还可以是静态存取区, 这都是看operator new的具体实现细节;
  2. 划分自由存储区和堆的界线就是new/delete与malloc/free;
  3. 很多编译器的new/delete都是以malloc/free为基础来实现的;
  4. operator new/delete可以进行重载;

为了在面试中眼前一亮, 可以更深入的回答

  1. 申请内存所在位置:

    • new操作符从自由存储区(free store)上为对象动态分配内存空间, 而malloc函数从堆上动态分配内存;
  2. 返回类型安全性:
    • new操作符内存分配成功时, 返回的是对象类型的指针, 类型严格与对象匹配, 无需进行类型转换, 所以new是符合类型安全性的操作符;
    • 而malloc内存分配成功则是返回泛型指针void, 需要通过强制类型转换将泛型指针void转换成我们需要的对象类型;
    • 类型安全很大程度上可以等价于内存安全, 类型安全的代码不会试图访问自己没有被授权的内存区域;
  3. 内存分配失败时的返回值:
    • new内存分配失败时, 会抛出bac_alloc异常, 它不会返回NULL指针;
    • malloc分配失败时会返回NULLl;
    • new根本不会返回NULL, 失败早就抛出异常了, 操作符不存在返回值一说。
  4. 是否需要指定内存大小:
    • new操作符申请内存分配时无须指定内存块的大小, 编译器会根据类型信息自行计算;
    • 而malloc则需要显式地指出所需内存的尺寸。
  5. 是否调用构造函数/析构函数:
    • 使用new操作符来分配对象内存时会经过三个步骤:

      • 调用operator new函数(对于数组是 operator new[])分配足够大的, 原始的, 未命名的内存空间以便存储特定类型的对象;
      • 编译器运行响应相应的构造函数以构造对象, 并为其传入初值;
      • 对象构造完成后, 返回一个指向该对象的指针;
    • 使用delete操作符来释放对象会经历两个步骤:
      • 调用对象的析构函数;
      • 编译器调用operator delete(或 operator delete[])操作符重载函数来释放内存空间;
    • new/delete会调用对象的构造/析构函数, 而malloc则不会;
    • 用malloc/free来处理C++的自定义类型是不合适的, 标准库中凡是需要构造/析构的类型通通不适合;
  6. 对数组的处理:
    • C++提供了new[]与delete[]来专门处理数组类型;
    • 使用new[]分配的内存必须使用delete[]进行释放;
    • new对数组的支持体现在它会分别调用构造函数初始化每一个数组元素, 释放对象时为每个对象调用析构函数;
    • 注意delete[]要与new[]配套使用, 不然会出现数组对象部分释放的现象, 造成内存泄漏;
    • 对于malloc, 它并不知道你在这块内存上要放的是数组还是别的东西, 反正它就给你一块原始的内存, 在给你一块内存地址就完事了;
    • malloc动态分配一个数组的内存, 还需要我们手动指定数组的大小;
  7. new与malloc是否可以相互调用:
    • 操作符new/delete的实现可以基于malloc, 而malloc的实现不可以去调用new;
  8. 是否可以被重载:
    • 操作符new/delete可以被重载, 标准库定义了new与delete的8个重载版本:
    //这些版本可能抛出异常
    void * operator new(size_t);
    void * operator new[](size_t);
    void * operator delete (void * );
    void * operator delete[](void *0;
    //这些版本承诺不抛出异常
    void * operator new(size_t ,nothrow_t&) noexcept;
    void * operator new[](size_t, nothrow_t& ) noexcept;
    void * operator delete (void *,nothrow_t& ) noexcept;
    void * operator delete[](void *0,nothrow_t& )noexcept;
    • 可以自定义这8个函数版本中的任意一个, 前提是自定义版本必须位于全局作用域或者类作用域中;
    • 我们有足够的自由去重载operator new/delete, 以决定我们的new与delete如何为对象分配内存, 如何回收对象;
    • 而malloc/free是并不允许重载的.
  9. 能够直观地重新分配内存:
    • 使用malloc分配内存后, 如果使用过程中发现内存不足, 可以使用realloc函数进行内存重新分配实现内存的扩充;
    • realloc先判断当前的指针所指向内存是否有足够的空间, 如果有, 原地扩大可分配的内存地址, 并且返回原来的地址指针;
    • 如果空间不够, 先按照新指定的大小分配空间, 将原有数据从头到尾拷贝到新分配的内存区域, 然后释放原来的内存区域;
    • new没有这样直观的配套设施来扩充内存;
  10. 客户处理内存分配不足;
    • 在operator new抛出异常以反映一个未获得满足的需求之前, 它会先调用一个用户指定的错误处理函数, 这就是new_handler;
    • new_handler是一个指针类型, 指向一个没有参数没有返回值的函数, 即错误处理函数;
    • 客户需要调用set_new_handler, set_new_handler的参数为new_handler指针, 指向operator new无法分配足够内存时该调用的函数;
    • 其返回值也是个指针, 指向set_new_handler被调用前正在执行(但马上就要发生替换)的那个new_handler函数.
    • 对于malloc, 客户并不能够去编程决定内存不足以分配时要干什么事情, 只能看着malloc返回NULL.

C++中有了malloc/free, 为什么还需要new/delete

  1. 回答这个问题,只需要强调malloc/free返回的是void*指针--就不会对对象进行构造, 而且空间不足的时候会直接返回NULL指针, 不会执行异常处理, 这样并不安全

delete 与 delete[]的区别

  1. delete只会调用一次析构函数,而delete[]会调用每一个成员的析构函数;
  2. 当delete操作符用于数组时,它为每个数组元素调用析构函数,然后调用operator delete来释放内存;
  3. delete与new配套,delete []与new []配套;
  4. 对于内建简单数据类型,delete和delete[]功能是相同的(因为内置类型没有析构函数)。对于自定义的复杂数据类型,delete和delete[]不能互用;
  5. delete[]删除一个数组,delete删除一个指针;

new-delete-malloc-free关系总结的更多相关文章

  1. 深入C++ new/delete,malloc/free解析

    深入C++ new/delete,malloc/free解析 1.malloc与free是C++/C语言的标准库函数.new/delete是C++的运算符. 它们都可用于申请动态内存和释放内存 2.对 ...

  2. C++ new delete malloc free

    title: C++ new delete malloc free date: 2020-03-10 categories: c++ tags: 语法 C++的new delete malloc fr ...

  3. 内存分配(new/delete,malloc/free,allocator,内存池)

    以下来源http://www.cnblogs.com/JCSU/articles/1051826.html 程序员们经常编写内存管理程序,往往提心吊胆.如果不想触雷,唯一的解决办法就是发现所有潜伏的地 ...

  4. new和delete malloc和free

    程序中动态分配的对象存放在自由存储区(free store)或堆(heap). C语言程序使用一对标准库函数malloc和free在自由存储区中分配存储空间,而C++语言则使用new和delete表达 ...

  5. new,delete,malloc,free

    malloc/free是C语言中的内存申请和释放函数,利用它们可方便地管理内存.而在C++中我们又有了新的工具:new/delete.new/delete在管理内存的同时会调用类的构造函数和析构函数, ...

  6. 内存分配方式,堆区,栈区,new/delete/malloc/free

    1.内存分配方式 内存分配方式有三种: [1]从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量,static变量. [2]在栈上创建.在执行函数时 ...

  7. C++之new/delete/malloc/free详解

    主要内容: 1.  C语言中的函数malloc和free 2.  C++中的运算符new和delete 3.  new/delete与malloc/free之间的联系和区别 4.  C/C++程序的内 ...

  8. C++/C语言的标准库函数与运算符的区别new/delete malloc/free

    malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符.它们都可用于申请动态内存和释放内存.下面来看他们的区别. 一.操作对象有所不同 malloc与free是C++ ...

  9. C/C++ 内存分配方式,堆区,栈区,new/delete/malloc/free

    内存分配方式 内存分配方式有三种: [1] 从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量, static 变量. [2] 在栈上创建.在执行函 ...

  10. 动态内存的分配(new delete malloc free)

    new和malloc的区别是什么?-new关键字是C++的一部分,在所有的C++编译器中都被支持-malloc是由C库提供的函数,在某些系统开发中是不能调用的-new以具体类型为单位进行内存分配-ma ...

随机推荐

  1. 13个.Net开源的网络爬虫

    请点击此处输入图片描述 1:.Net开源的跨平台爬虫框架 DotnetSpider Star:430 DotnetSpider这是国人开源的一个跨平台.高性能.轻量级的爬虫软件,采用 C# 开发.目前 ...

  2. idea 快捷键ctrl+shift+f失效的解决方案

    我是使用微软自带的拼音输入法,右下角图标--右键--设置--按键,拉到最下面 ---快捷键(简体繁体切换),取消勾选 即可

  3. 【leetcode-89 动态规划】 格雷编码

    ( 中等难度题(×) -背答案题(√) ) 格雷编码是一个二进制数字系统,在该系统中,两个连续的数值仅有一个位数的差异. 给定一个代表编码总位数的非负整数 n,打印其格雷编码序列.格雷编码序列必须以 ...

  4. 066、Weave如何与外网通信?(2019-04-09 周二)

    参考https://www.cnblogs.com/CloudMan6/p/7500550.html   Weave是一个私有的vxlan网络,默认与外部网络隔离.外部网络如何才能访问到weave中的 ...

  5. 我的长大app开发教程第三弹:实现四个子页面绑定RadioButton

    在开始之前先上一张图 在上一节中我们实现了底部Button,这一弹我们要实现点击四个按钮分别切换到不同页面,我们可以把页面分为两部分,顶部栏和中间内容部分,我们可以通过线性布局包裹两部分内容,顶部栏又 ...

  6. docker 系列 - 企业级私有镜像仓库Harbor部署(转载)

     本文转载自 搜云库 的文章 https://www.jianshu.com/p/7d76850de03f  , 感谢作者 3.png 上一篇文章搭建了一个具有基础功能,权限认证.TLS 的私有仓库, ...

  7. springboot(十七):过滤器(Filter)和拦截器(Interceptor)

    概述 在做web开发的时候,过滤器(Filter)和拦截器(Interceptor)很常见,通俗的讲,过滤器可以简单理解为“取你所想取”,忽视掉那些你不想要的东西:拦截器可以简单理解为“拒你所想拒”, ...

  8. extjs.net Combox赋值

    1.直接赋值 ].Rows) //遍历获取两个值 { Ext.Net.ListItem listItem = new Ext.Net.ListItem(); //每次创建一个Ext.Net.ListI ...

  9. DAO层设计

    一.类图分析 二.参考文档 ( JavaBean中DAO设计模式介绍)(附:设计源码) 三.类图设计文件 百度云盘:https://pan.baidu.com/s/1i5xaS8P[Power Des ...

  10. Kafka如何保证消息不丢失不重复

    首先需要思考下边几个问题: 消息丢失是什么造成的,从生产端和消费端两个角度来考虑 消息重复是什么造成的,从生产端和消费端两个角度来考虑 如何保证消息有序 如果保证消息不重不漏,损失的是什么 大概总结下 ...