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分配内存的自由链表结构
比如此时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的重载来保证堆的稳定;
最后,在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大小空间