一、前言
学习过C语言会晓得,在C语言中,动静分配内存用malloc()函数,开释内存用free()函数。在C++中这2个函数还是能够应用的,然而C++新增了2个关键字:new和delete。new 用来动静分配内存,delete 用来开释内存。咱们能够这样应用:
int* p = new int;delete p;或int* pArray= new int[20];delete[] pArray;
new 操作符会依据前面的数据类型来推断所需空间的大小。由上可知,应用new调配的内存用delete开释,应用new[]调配的内存用delete[]开释,它们是一一对应的。
new申请空间时会多申请4个字节,用于寄存对象的个数,在返回地址时则会向后偏移4个字节,在delete时则会查看内存上对象的个数,依据个数确定调用几次析构函数,这样能力齐全清理所有对象占用的内存,因而对于内置类型若new[],应用delete开释,没有影响;但若是自定义类型,应用delete开释时只会调用一次析构函数,就会存在有对象没有被析构的状况。
new是在自在存储区上分配内存(能够在堆上,也能够在动态存储区上,取决于operator new实现细节,取决与它在哪里为对象调配空间),必须手动开释,否则只能等到程序运行完结由操作系统回收。为了防止内存透露,new 和 delete、new[] 和 delete[] 操作符应该成对呈现,并且不要和C语言中 malloc()、free() 一起混用。
在C++中最好应用new和delete治理内存,比C语言的malloc和free多了能够主动调用构造函数和析构函数,这样在程序运行完结时能够开释内存。
二、new、delete和malloc、free的区别
1、new和delete
new在操作时,内存通过 operator new 函数被调配,而且会为被调配的内存调用一个或多个构造函数构建对象;new内置了sizeof、类型转换和类型安全检查性能,对于非外部数据类型的对象而言,new 在创立动静对象的同时实现了初始化工作。如果对象有多个构造函数,那么new 的语句也能够有多种形式。如:
int *p= new int[100](1);// 创立100 个动静对象的同时赋初值1
delete时,会为将被开释的内存调用一个或多个析构函数,还会通过 operator delete 函数开释内存。
2、malloc和free
malloc的函数原型为
void *malloc(long NumBytes)
由原型可知,调用malloc时须要指定分配内存的字节数,胜利调配的话就返回对应的指针,指向被调配的内存块起始地位;否则返回空指针。
free的函数原型为:
void free(void *p)
将之前用malloc调配的空间还给程序或者操作系统,即对malloc申请的内存空间进行开释。
free函数开释的是指针指向的内存(不是开释的指针自身,不会删除指针自身), 其中指针必须指向所开释内存空间的首地址。如果p 不是NULL 指针,那么free 对p间断操作两次就会导致程序运行谬误。
3、本质区别
1)malloc/free是C/C++语言的规范库函数,new/delete是C++的运算符
2)new能够主动分配内存空间,malloc须要指定申请空间的大小
3)对于用户自定义的对象而言,malloc/free无奈满足动静治理对象的要求。因为malloc/free是库函数而不是运算符,不再编译器管制权限之内,不可能把执行构造函数和析构函数的工作强加于malloc/free。
new/delete能够被重载,malloc/free不能够;
new/delete底层是基于malloc/free实现的;
malloc分配内存之后发现不够,可通过realloc函数对其进行裁减或放大;
malloc申请内存时返回内存地址要查看判空,因为申请失败时返回NULL;new不必判断,在内存调配失败时会抛出异样bac_alloc,因而可在new时加上异样解决机制,如:
int* p = new(std::nothrow) int[10];
为什么还保留了malloc和free?C++程序常常要调用C函数,而C程序 只能用malloc/free治理动态内存。若应用free开释new创立的动静对象,对象会因无奈执行析构函数而导致程序出错。若delete开释malloc申请的动态内存,可能不会出错,但程序的可读性差。