• C++中的动态内存管理


    malloc/free和new/delete之间关系和差异

    相同点:

    都可用于申请动态内存和释放内存

    不同点:

    (1)操作对象不同
    malloc/free是C++/c语言的标准库函数,new/delete是c++的运算符,对于非内部数据类型的对象而言,只有malloc、free是无法满足动态对象的要求的。因为对象在创建的时候会自动调用构造函数,对象消亡时会自动调用析构函数。因为malloc/free是库函数而不是运算符,不在编译器控制的范围内,不能够执行构造函和析构函数
    (2)用法不同
    函数malloc 的原型如下:
    void*malloc(size_t size)
    用malloc申请一块长度为n的整数类型的空间,代码如下
    int p = (int)malloc(sizeof(int)*n);
    注意:
    <1>. malloc返回值是void* ,岁哟调用时要进行显示的类型转换,讲void* 转换成所需要的类型
    <2>.malloc函数本身并不识别要申请的内存是什么类型,只关心内存的总字节数
    函数free的原型:
    void free(void* memblock)
    为什么free函数不像malloc函数那样复杂呢?这是因为指针p 的类型以及他所指向的内存的容量都是事先知道的,free(p)才可以正确的释放p,如果p是NULL,free对p乌云操作多少次都不会出现问题,而如果p不是NULL,那么free进行两次就会出现错误,就是已经释放的空间连续释放,就会出现问题
    new、delete
    运算符new 使用起来要比函数malloc 简单得多,例如:
    int p1 = (int )malloc(sizeof(int) * length);
    int *p2 = new int[length];
    这是因为new 内置了sizeof、类型转换和类型安全检查功能。对于非内部数据类型的对象而言,new 在创建动态对象的同时完成了初始化工作。
    delete是与new成对出现的,new/delete new[]/delete[] 注意一定要成对使用

    1、本质区别
    malloc/free是C/C++语言的标准库函数,new/delete是C++的运算符。
    对于用户自定义的对象而言,用maloc/free无法满足动态管理对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。因此C++需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。
    2、联系:
    既然new/delete的功能完全覆盖了malloc/free,为什么C++还保留malloc/free呢?因为C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。如果用free释放“new创建的动态对象”,那么该对象因无法执行析构函数而可能导致程序出错。如果用delete释放“malloc申请的动态内存”,理论上讲程序不会出错,但是该程序的可读性很差。所以new/delete、malloc/free必须配对使用。

    剖析new/delete、new[]/delete[]到底做了些什么事情。

    这里写图片描述

    这里写图片描述
    不管是new还是new[] 都调用了operator new函数,在operator new函数中,又调用了malloc函数。
    当然new[] 调用了operator new[] 而operator new[] 又调用了operator new函数。
    在底层实现中,new就是用malloc函数来开辟空间的。

    实现NEW_ARRAY/DELETE_ARRAY宏,模拟new[]/delete[]申请和释放数组。

    #define NEW_ARRAY(PTR,TYPE,N)
     do                          
    {PTR = (TYPE*)operator new(sizeof(TYPE)*N+4)
        (*(int*)PTR) = N                         
        for(size_t i = 0;i<N;i++)               
        new (PTR+i)TYPE;                        
    }while(false);
    //为什么在申请空间的时候要多申请四个字节呢?这是因为需要用来记录对象的个数,可以知道在析构的是后要调用几次
    //析构函数
    #define DELETE_ARRAY(PTR,TYPE)      
        do{int N = *((int*)PTR-1) //这里取出保存的对象的个数   
        for(size_t i=0;i<N;i++)         
    {PTR[i].~TYPE();                    
    PTR = (TYPE*)((char*)PTR-4);        
        operator  delete(PTR); }          
        }while(false);
    //注意:在用宏实现的收,一定要加上续行符。
  • 相关阅读:
    Java
    Java
    Java与正则表达式
    Java与UML
    用IKVMC将jar转成dll供c#调用
    日历
    提取多层嵌套Json数据
    微信公众平台获取用户openid
    配置IISExpress允许外部访问
    英文单词学习
  • 原文地址:https://www.cnblogs.com/chan0311/p/9427336.html
Copyright © 2020-2023  润新知