zoukankan      html  css  js  c++  java
  • new、delete、malloc、free、realloc的区别

    1、属性

    new/delete是C++的运算符,malloc/free是标准库函数

    2、参数

    new运算符根据数据类型,自动决定其大小,不使用sizeof运算符,而malloc要指定分配存储空间的大小。

    3、返回类型

    new返回指向此类型的指针,不用进行强制类型转换。故new是符合类型安全性的操作符。malloc返回指向void *类型的指针,需要进行强制类型转换。

    4、初始化

    new是一个分配内存并进行初始化的过程,例如,cha *p = new char(‘a');而malloc()仅仅是一个函数,没有初始化的过程,需要编码人员手动初始化。

    5、分配失败

    malloc分配内存失败时返回NULL,new内存分配失败时,有两种情况:

    1)抛出bad_alloc异常来报告分配失败;

    2)返回空指针,而不会抛出异常。

     首先,c++是在c语言的基础之上发展而来,而且c++发明时是想尽可能的与c语言兼容。而c语言是一种没有异常机制的语言,所以c++应该会提供一种没有异常机制的new分配内存失败报告机制;(确实是如此,早期的c++还没有加入异常机制),其次在返回空指针的实现过程中,c++采用的是malloc/calloc 等分配内存的函数,该类函数不会抛出异常,但是在分配内存失败时会返回“空指针”。最后,对于标准的c++,有着比较完善的异常处理机制,所以对于出现异常时,会抛出响应的异常。对于new分配失败时,系统会抛出bad_alloc异常。

    所以具体是那种情况,看编译器对标准c++的支持情况。

    6、自定义类型(类等)

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

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

    7、重载

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

    8、 内存区域

    new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。自由存储区不等于堆,如上所述,布局new就可以不位于堆中。

    自由存储区是否可以是堆?这取决于operate new 的实现细节。自由存储区不仅仅可以是堆,还可以是静态存储区,这取决于operate new 在哪里为对象分配内存。

    十个区别:

    特征new/deletemalloc/free
    分配内存的位置 自由存储区
    内存分配成功返回 完整类型指针 void*
    内存分配失败返回值 默认抛出异常 返回NULL
    分配内存的大小 由编译器根据类型计算得出 必须显式指定字节数
    处理数组 有处理数组的new版本new[] 需要用户计算数组的大小后进行内存分配
    已分配内存的扩充 无法直观地处理 使用realloc简单完成
    是否相互调用 可以,看具体的operator new/delete实现 不可调用new
    分配内存时内存不足 客户能够指定处理函数或重新制定分配器 无法通过用户代码进行处理
    函数重载 允许 不允许
    构造函数与析构函数 调用 不调用

    a)malloc 可以通过realloc重新分配内存大小

    void *raealloc(void *ptr,size_t size)

    void *ptr表示之前malloc分配内存空间的首地址,size是新的内存大小。注意新分配大小不能比malloc所申请的小,否则会造成数据丢失。

    b)在使用delete后,注意将指针置为NULL,否则会形成悬垂指针(指针所指内存已被释放,仍指向该内存),造成错误

    这是因为delete后,虽然内存释放的了,但是指针所指向的地址仍未改变,只是内容被清除。后续代码任然可以调用。

    c)new与delete,new a[ ]与delete [ ] a成对使用,除了(当new的内存空间分配给没有显式定义给、析构函数类的指针,可以使用delete[ ]释放)

     PS:在C++中,内存区分为5个区,分别是堆、栈、自由存储区、全局/静态存储区、常量存储区;

     在C中,C内存区分为堆、栈、全局/静态存储区、常量存储区;

  • 相关阅读:
    61个下拉菜单实例
    简单图片放大效果
    QQ,MSN,Skype在线客服代码
    codesmith自定义模板之实体层
    如何利用缓存提高ASP.NET网站速度
    10+Jquery Tooltip Plugins and Tutorial Collection
    10个ajax 上传插件
    ASP.NET 中 “返回上一页”,“上一步”的实现方法
    执行多条SQL语句,事务处理
    [Asp.Net+C#]Datagrid使用技巧四(怎样控制在一个单元格中放置多个操作按钮及删除数据)
  • 原文地址:https://www.cnblogs.com/zyever/p/9644350.html
Copyright © 2011-2022 走看看