关于malloc/free && new/delete

来源:互联网 发布:网游加速器 知乎 编辑:程序博客网 时间:2024/06/05 10:39

point of division

1:总结并剖析malloc/free和new/delete之间关系和差异。
2:剖析new/delete、new[]/delete[]到底做了些什么事情。
3:实现NEW_ARRAY/DELETE_ARRAY宏,模拟new[]/delete[]申请和释放数组。

                                                                                                                                                                                                                                                                                       

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

首先,分别介绍一下:


malloc/free:


1、函数原型及说明:

void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针。如果分配失败,则返回一个空指针(NULL)。

void free(void *FirstByte): 该函数是将之前用malloc分配的空间还给程序或者是操作系统,也就是释放了这块内存,让它重新得到自由。


2.内存操作:

malloc函数的参数是接受需要分配的内存字节数,如果内存能够满足请求量,那么将会返回:指向被分配的内存块起始位置

free函数释放的是指针指向的内存(不是释放的指针本身,不会删除指针本身),其中指针必须指向所释放内存空间的首地址


new/delete

1.new/delete都是操作符。

2.操作时发生事件:
new的时候会有两个事件发生:1).内存被分配(通过operator new 函数)  2).为被分配的内存调用一个或多个构造函数构建对象
delete的时候,也有两件事发生:1).为将被释放的内存调用一个或多个析构函数  2).释放内存(通过operator delete 函数)。

3.特殊应用:
使用delete是未加括号,delete便假设删除对象是单一对象。否则便假设删除对象是个数组。
因此,如果在调用new时使用了[],则在调用delete时也使用[],如果你在调用new的时候没有[],那么也不应该在调用时使用[]。


malloc/free 和new/delete 的本质区别:

1.malloc/free是C/C++语言的标准库函数,new/delete是C++的运算符。

2.new能够自动分配空间大小,new/delete是可以重载的,而重载之后,就成为了函数。

3.malloc在申请内存的时候,必须要提供申请的长度,而返回的指针是void*型,必须要强转才能成为需要的类型。

4.对于用户自定义的对象而言,用maloc/free无法满足动态管理对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。
由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。
因此C++需要一个能对对象完成动态内存分配和初始化工作的运算符new,以及一个能对对象完成清理与释放内存工作的运算符delete---简而言之 new/delete能进行对对象进行构造和析构函数的调用进而对内存进行更加详细的工作,而malloc/free不能。

相同点:

1. 都必须配对使用,这里的配对使用,可不能理解为一个new/malloc就对应一个delete/free,而是指在作用域内,new/malloc所申请的内存,必须被有效释放,否则将会导致内存泄露。

2. 都是申请内存,释放内存,free和delete可以释放NULL指针。

注:C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。如果用free释放“new创建的动态对象”,那么该对象因无法执行析构函数而可能导致程序出错。如果用delete释放“malloc申请的动态内存”,理论上讲程序不会出错,但是该程序的可读性很差。所以new/delete,malloc/free必须配对使用。


2.剖析new/delete、new[]/delete[]到底所做了什么

new/delete

在使用new的时候做了两件事:
1、调用operator new分配空间
2、调用构造函数初始化对象

在使用delete的时候也做了两件事:
1、调用析构函数清理对象
2、调用operator delete函数释放空间

new[]/delete[]

在使用new[N]的时候也做了两件事:
1、调用operator new分配空间
2、调用N次构造函数初始化N个对象

在使用delete[]的时候也做了两件事:
1、调用N次析构函数清理N个对象
2、调用operator delete函数释放空间


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

#define NEWARRAY(PTR, TYPE, N)                                \do                                                    \{                                                     \PTR = (TYPE*)operator new(sizeof(TYPE)*N + 4);\(*(int*)PTR) = N;                             \PTR = (TYPE*)((char*)PTR + 4);                \for (size_t i = 0; i < N; ++i)                \new(PTR + i)TYPE;                     \} while (false);                                      \#define DELETEARRAY(PTR, TYPE)        \do                                    \{                                     \size_t 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);                      \