天天看点

c中已经有了malloc和free,为什么c++中会用new和delete?

要了解这个问题我们先需要了解它们的区别

相同点:都会从堆上申请空间,用户需要自己来管理。 

不同点:

 1.所属语言 

new是C++特性,malloc是C的。C++一般使用的new,但也可以使用malloc,而C用malloc、realloc、calloc。

2.申请释放方式 

new和delete,malloc和free配对使用。new的使用比malloc简单,内部已经实现了大小的计算、类型转换等工作,而malloc使用时需要计算大小及进行类型转换。 

3.malloc是标准库函数,new是C++的运算符。 

new可以被重载,但malloc不可以,malloc需要库函数的支持,new不需要。

4.构造与析构 

new和delete会自动调用构造函数和析构函数,但是malloc和free不会。

5.申请内存失败 

申请内存失败,默认new抛出异常,malloc返回NULL。 

6.重新分配内存 

malloc可利用realloc重新分配内存,new不可以。 

7.类型安全性 

new会检查类型是否对应,如果不对应会保存,但malloc只关注申请内存的多少,不会检查类型。 

8.类型转换 

malloc返回的类型是void,所以在调用malloc时要进行显式的类型转换,将void转换成所需的指针类型,new不需要。

9.数组分配 

new有明确的方式处理数组的分配,即new[],释放也有delete[],malloc没有。 

10.设置内存分配器 

new可以设置自己的内存分配器,malloc不可以。

如果上述内容你已经完全了解了,那么请看下面的进阶内容

1、new/delete、new[]/delete[]

new、delete是操作符,用来分配空间和清理对象的。new[]、delete[]是来为对象数组分配空间和清理对象的。

int* p1=new int;//分配一个int大小的空间 
int* p2=new int(3);//分配一块空间,并将空间初始化成3. 
int* p3=new int[3];//分配3个int对象的空间。           

2、底层原理

其他内存管理接口 operator new/operator delete、operator new[]/operator delete[]

!!!operator …不是new/delete的重载!!!

总结:

operator new/operator delete、operator new[]/operator delete[]与malloc/free用法一样。 

负责分配空间/释放空间,但是不会调用构造函数和析构函数来初始化/清理对象。 

实际上operator new/operator delete是malloc/free的一层封装。

new 做了两件事 

  • 1. 调用operator new分配空间。 
  • 2. 调用构造函数初始化对象。

delete做了两件事 

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

new [N] 

  • 1. 调用operator new分配空间。 
  • 2. 调用N此构造函数来初始化对象。

delete[N] 

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

问题来了?那么数组底层是怎么知道要调用N次析构函数的呢?

c中已经有了malloc和free,为什么c++中会用new和delete?

(为了对象)简单的说就是多开辟了四个字节用来保存调用了多少构造函数。

感觉抽象的话我们先看下这张图,然后下来看下下面四种情况

c中已经有了malloc和free,为什么c++中会用new和delete?
//(1)不会崩溃,虽然没有调用析构函数 
AA* p0=new AA; 
free p0;
//(2)程序会崩溃,因为delete[]在对象使用完成后会默认将指针-4,取到最前面的位置调用析构函数,但是构造对象的时候是从当前位置开始的,所以就会出现指针越界,程序就会崩溃。 
AA* p1=new AA; 
delete[] p1;
//(3)程序会崩溃,free不会偏移4个字节,释放位置错误 
AA* p2=new AA[10]; 
free p2;
//(4)程序会崩溃,虽然delete只析构一次,但是这不是程序崩溃的原因,主要原因是 释放位置错误 
AA* p3=new AA[10]; 
delete p3;

//注AA为自定义类型
           

内置类型假如不匹配也不会崩溃,是由于内置类型在开空间的时候不会多开四个字节!!!