malloc与free、new与delete

(一)malloc与free

1.void *malloc(int size);

它的返回值为void*,表示分配的堆内存的起始地址,返回值可以被强转为任何类型的指针;

并且malloc函数分配得到的内存空间是未初始化,一般要调用memset函数将其初始化为0;

void *memset(void *p,int c,int n);

该函数可以将指定的内存空间按字节单位置为指定的字符c;

其中p为要清零的内存空间的首地址,n为要操作的内存空间的字节长度,如果要用memset清零,c置为0;

2.void free(void *p);

用来释放由malloc开辟的内存空间,但是不将指针置为NULL;

(二)new与delete

1.new是C++的运算符,也可以用于动态开辟内存空间,在使用时既可以初始化空间也可以不进行初始化空间

开辟一个空间 int *p1 = new int ;//未初始化   int *p2 = new int(10);//开辟一个整型大小空间并将此空间置为10;

开辟一个数组int *arr = new int[10];//开辟了10个整型大小的空间

2.delete也是一个运算符 用来释放new开辟的空间,并将指针置为NULL,避免造成野指针

delete p1;//释放单个空间  delete []p2;//释放数组空间

(三)有了malloc与free,为什么要有new与delete呢?

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

2.对于非内置类型的对象来说,在在对象创建的同时需要自动调用构造函数,在对象消亡的时候自动调用析构函数,但是对于malloc与free是标准库函数,不在编译器的控制范围之内,不能用于非内置类型对象的创建于析构;

3.对于内置类型的对象是没有构造与析构过程的;所以malloc与free、new与delete是等价的;

4.由于C++程序经常调用c函数,而c程序只能由malloc与free管理动态内存

5.new可以实现C++语言动态分配内存和初始化的功能;delete可以实现C++语言清理与释放内存的功能;

6.malloc与free、new与delete必须配对使用,不可以混用,会导致程序出错

(四)malloc与new的区别

1.从本质上看,new是C++语言的运算符,malloc是C语言标准库函数;

2.从功能上看,new是开辟内存+初始化,malloc只是开辟内存;

3.new不需要外部计算大小,malloc需要计算大小;

4.new安全 ,malloc不安全;malloc分配空间必须检查是否为NULL,不再使用时free空间必须将指针置为NULL,避免野指针;

5.内存不足时,new会抛出bad_alloc异常,malloc返回NULL;

6.new是从自由链表区分配内存,malloc是从堆区分配内存;

7.operator new 可以重载,malloc不能重载;

8.new可以调用malloc,但是malloc不能调用new;

为new分配内存的自由链表结构

malloc与free、new与delete

比如此时int *p = new int ];则是在数组0号下标对应的链表的中通过头删的方式将节点分配给new再将剩余节点与指针p1相联系

比如为一个内置类型(12)字节分配空间,那么在数组1号下标对应的链表中分配节点;

只要new所申请分配的空间小于等于128字节,都是在此自由链表中分配,如果不在使用进行释放后也是归还给自由链表;

为malloc分配的链表也是如此,操作系统中有一个记录空闲内存地址的链表,当操作系统接收到程序的申请时,会遍历该链表,寻找第一个空间节点大于所申请空间的堆节点,然后将该结点从链表删除并将节点的空间分配给程序;归还时也是返还给链表。
(五)operator new、operator delete

这两个运算符函数的原型:

void *operator new(size_t size);//底层调用malloc

void *operator delete(void *p);//底层调用free

void *operator new[](size_t size);//底层调用malloc

void *operator delete[](void *);//底层调用free

new总共做了两件事
 1.调用operator new函数分配空间
 2.调用构造函数初始化对象

delete也做了两件事
 1.调用析构函数清理对象
 2.调用operator delete函数释放空间

new[n]
 1.调用operator new[]分配空间。
 2.调用n次构造函数分别初始化每个对象。

delete[]
 1.调用n次析构函数清理对象。
 2.调用operator delete[]释放空间

需要注意的是operator new /delete operator new[]/delete[]只负责分配空间/释放空间,不会调用对象构造函数,析构函数来初始化或清理对象。实际operator new和operator delete只是malloc和free的一层封装。

c++对内存的管理非常安全:是因为当一个对象被消除时,它的析构函数能够安全的释放所分配的内存;

由于频繁使用new和delete,使得很容易造成堆破损的风险,所以在对于不同的对象中,可以实现对new和delete的重载来保证堆的稳定;

malloc与free、new与delete

最后,在new arr[N]时,其中operator new[]中size= sizeof(arr)*N+4,多出来的四个字节是为了存放需要调用构造函数的系数

同理。delete时,先拿到前四个字节需要调用析构函数的次数,在进行析构;

(六)重定位new

1.int *p = new int; p = new(p) int(10);//

2.int *p = (int *)operator new(sizeof(int));

   p = new(p) int (10);

3.char buff[1024] = {};

   char*p = new(buff) char[100];//p指向buff所占内存的前100个char大小空间