一、简说
new和delete是C++的关键字,通过new和delete可以在堆上开辟和释放空间。
在C语言中我们通过malloc和free对堆上的内存进行申请和释放。
在C++中,则需要对类的对象进行管理。用new和delete管理对象,new[]和delete[]管理对象数组。它们之间要对应使用。
void Test()
{
int *p = (int*)malloc(4);
int *p1 = new int;//p1指向int类型大小的空间
int *p2 = new int(1);//p2指向int类型大小的空间,并初始化为1
int *p3 = new int[5];//p3指向有5个int元素的数组类型大小,20字节
。它们之间要对应使用。delete p1;
delete p2;
delete[] p3;
}
二、new和delete
1.new运算符的内部实现
- 内存分配
调用operator new(size_t)函数,而operator new(size_t)函数又会调用malloc函数申请空间。如果申请失败则抛异常。
- 初始化
在分配的内存上调用构造函数对对象进行初始化,并返回地址。如果初始化对象失败,则抛异常并调用operator delete(void*)函数释放已申请的内存。
2.delete运算符的内部实现
调用对应类型的析构函数,清理对象,内存释放
调用operator delete(void*)函数,operator delete(void*)会调用free函数释放内存
三、提问三连
new和delete与new[]和delete[]有什么不同?
new[]在调用operator new申请空间会多申请4个字节用于存放元素个数,分配完成指针向后偏移4个字节供用户使用,且会调用N次构造函数分别初始化每个对象。
而delete[]会向前移动4个字节,得到元素个数,调用N次析构函数清理对象。再调用operator delete释放空间,当然开头4字节也会被释放掉。如果new和delete[],new[]和delete匹配使用,会怎么样?
delete[]释放new开辟的空间,会向前偏移4字节读取元素个数,造成释放错误。delete释放new[]的空间,会造成少释放前4字节,并因为不知道该释放多少个元素造成内存泄漏。
如果用free释放new,delete释放malloc申请的空间?
class Person
{
public:
Person()
{
name = new char[8];
}
~Person()
{
delete[] name;
}
char *name;
};
void Test()
{
Person*p1 = new Person;
free(p1);
Person*p2 = (Person*)malloc(sizeof(Person));
delete(p2);
}
p1指向new出来的对象。对象通过构造已经初始化。如果直接free(p1),则只对p1的空间free,而对象内name动态开辟的空间没有释放。
p2指向一个malloc出来,对象大小的空间,该块空间没有通过构造函数初始化。delete(p2),会调用析构函数,name没有初始化指向哪块空间,delete[]会造成程序崩溃。
因此,new和delete,new[]和delete[],malloc和free应匹配使用。
四、new和malloc的区别?
new是操作符,malloc是函数。
new在堆上分配空间后会调用构造函数进行初始化,而malloc只管分配空间。
new作用于内置类型和自定义类型,而malloc只能作用于内置类型。
new开辟空间大小由系统计算,而malloc根据传参确定。
new返回值是对应数据类型指针,malloc返回值是void*。
new与delete匹配使用,malloc和free匹配使用。