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);
//注意:在用宏实现的收,一定要加上续行符。 
                     
                    
                 
                    
                 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号