1.我们先来讲述一下new和delete?
在C++中new/delete是开辟/释放内存的,那他们与C语言中的malloc/free有什么区别呢?
(1)new的底层是通过malloc来开辟内存的,但new比malloc多一项功能,那功能就是开辟完内存还要进行初始化操作。
比如:new的基本操作为:int *p=new int(10);10代表堆上开辟的整型内存的初始值;Test *p=new Tset();这个操 作不仅会在堆上开辟Test类型大小的一块内存,还会调用Test类的默认构造函数构造一个对象,然而这时malloc办不到 的!
(2)delete比free多一项功能:在释放内存之前,还可以析构指针指向对象。new和delete配套使用,new【】和delete【】配套 使用。尽量不要交叉使用;
(3)new的开辟内存失败是抛出bad_malloc类型异常,因此代码要捕获该类型的异常才正确的判断内存是否分配成功,malloc 内存开辟失败返回的是NULL指针;
(4)new和delete不仅是运算符,他们不仅是运算符重载函数的调用,对应函数名是operator new和operator delete,可以全局 或类中作用域提供自定义的new和delete运算符的重载函数 ,以改变默认的malloc和free内存开辟释放内存,比如实现内存 池。
2.什么时候用new【】申请,可以用delete释放?
new和new【】的底层都是通过malloc来开辟内存,delete和delete【】的底层都是通过free来释放内存。那C++种为什么把单个元素的内存开辟释放和数组的内存开辟释放分开呢?因为在C++中开辟内存和构造对象是一起发生的,析构对象和内存是一起发生的。对于如下的类型:
int *p=new int ; delete p;
int *p=new int ; delete []p;
int *p=new int[10] ; delete []p;
int *p=new int[10] ; delete p;
对于内置类型来说,这样混用是可以的,因为这个内置类型没有提供构造和析构函数,因此在这里的内存管理和调用malloc、free的含义是一样的,不会存在什么问题。但这样的代码是不符合编码规范的!!!
对于如下的代码:
class Test
{
public:
Test(){};
private:
int ma;
};
Test *p=net Test; delete p;
Test *p=new Tset; delete []p;
Test *p=new Test[10]; delete []p;
Test *p=new Test[10]; delete p;
对于以上代码没有问题,因为这类没有提供析构函数,也就是说这个Test类对象不需要进行任何有效的析构,那么delete就只剩free的功能。那什么时候必须配套使用呢?接下来我们看看以下代码:
class Test
{
public:
Test(){};
~Test(){};
private:
int ma;
};
Test *p=new Test; delete p;//这个是OK的
Test *p=new Test; delete []p;//程序崩溃
Test *p=new Test[10]; delete []p;//这个是OK的
Test *p=new Test[10]; delete p;//程序崩溃
这几行代码和上面的代码的不同点是:该代码有自定义的构造和析构函数。Test *p=new Test; delete []p;此行代码开辟了4个字节。当delete去释放内存时,那他是如何释放内存的,为什么释放4个字节?
在这里我们自定义了析构函数,在释放内存前要析构对象。那我们写delete []p,编译器就会认为这里有很多对象要被析构,然而我们不知道有多少对象要被析构。记录对象个数的数字就在对象的4个字节存放着,他要从这里开始释放内存,然而这是错误的。
因此,在我们用了自定义类型,而且还提供了析构函数时,new和delete要配套使用。
3.new和malloc的区别
(1)malloc是函数,开辟内存需要传入需要字数,如malloc(100);表示在堆上开辟了100个字节的内存,返回void *,表示分配的堆内存的起始地址,因此malloc的返回值需要强转成指定的类型。new是运算符,开辟内存需要指定类型,返回指定的类型,因此不需要强转;
(2)malloc和new都是在堆上开辟内存的。malloc指负责开辟内存,没有初始化功能,需要用户自己初始化;new不但开辟内存,还可以进行初始化;
(3)malloc开辟内存失败返回NULL,new开辟内存失败抛出bad_malloc类型的异常,需要捕获异常才能判断内存开辟内存成功或失败。new运算符其实是operator new函数的调用,它底层调用调用的是malloc来开辟内存。new他比malloc多的初始化功能。对于类型来说,所谓初始化就是调用相应的构造函数;
(4)malloc开辟的内存永远是通过free来释放的;而new是单个元素内存,用的delete。如果是new【】数组,用的delete【】来释放内存;
(5)malloc开辟的内存是只是一种方式,而new有四种,分别是普通的new(内存开辟内存失败抛出异常bad_malloc异常),northrow版本的new、const new以及定位new;
(6)重载。C++允许重载new/delete操作符,在布局new的就不需要作为对象分配牛从哪,而是指定一个地址作为内存起始地址,在这段内存上为对象调用构造函数完成初始化工作,并返回地址。而malloc不允许重载。
4.有了malloc/free,为什还需要new/delete??
malloc/free是C/C++中标准库函数,new/delete是C/C++中的关键字,都是开辟内存和释放内存的。malloc/free只能满足库内的数据类型,无法满足动态开辟对象的要求。对象在创建时调用构造函数,销毁时调用析构函数。malloc/free是库内提供的函数而不是运算符,不在编译器的范围之内,不能够把执行构造函数和析构函数的任务强加于他。C++需要一个能够完成开辟内存和调用构造函数的new,对象销毁时释放内存和调用析构函数的delete
————————————————
版权声明:本文为CSDN博主「つ微凉徒眸意浅挚半~~」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/rjp_1987/article/details/104539467