new和malloc的区别
new malloc
- new不需要传入开辟内存的大小 malloc需要传入开辟内存的大小
- new和delete是两个关键字 malloc和free是两个函数
- new的返回值类型安全 malloc的返回值(void*)不安全
- new开辟内存失败时,抛出异常 malloc开辟内存失败时,返回NULL
- new不仅能开辟内存,还能进行初始化 malloc只能开辟内存,不能初始化
- new开辟的内存叫做自由存储区 malloc开辟的内存叫做堆区
- new可以重载 malloc不能重载
- new开辟数组时用[ ]传入数组的大小
重定位new
int a = 10;
char* p = new(&a)char('a');
例如,在上述这个重定位new的例子中指的是,在int型变量a的4个字节的内存中,划分出来一个字节的大小,用来存放字符'a'。
class Test
{
public:
Test(int data = 10):ma(data)
{
cout<<"Test()"<<endl;
}
~Test()
{
cout<<"~Test()"<<endl;
private:
int ma;
}
int main()
{
Test *p1 = new Test[5];
delete []p1;
return 0;
}
我们在堆上开辟了5个Test对象,并用栈上的一个指针p1指向这个对象数组,我们对发现,在使用new关键字开辟这个对象数组时我们人为的传入了这个对象数组的大小5,但在调用delete释放这块内存时,却没有传入对象数组的大小5,那么系统这时怎么知道我们要释放的对象数组是多大呢?
实际上,系统还会额外的开辟4个字节的内存,用这4个字节的内存来保存实际开辟的对象数组的大小,而这个额外的内存的地址就是对象数组的首地址-4,并且在开辟完成后,返回给p1指针的地址也是对象数组的首地址。
在进行delete操作时,因为delete后面连着的是[ ] ,因此系统知道当前要释放内存的是一个数组。首先会调用析构函数,将这个对象数组析构,接着系统会给当前要释放的内存空间的地址-4,查看要释放的数组的大小是多少,得到当前要释放的对象数组的大小是5后,便使用free函数,分别将存放对象数组大小的内存空间和对象数组的内存空间释放掉。