在C++中,申请动态内存与释放动态内存,用new/delete与malloc/free都可以;而且它们的存储方式相同,new/malloc动态申请的内存都位于堆中,无法被操作系统自动回收,需要对应的delete/free来释放空间。此外,对于一般的数据类型,如int、char,它们的效果是一样的。
malloc/free是C/C++语言的标准库函数,在C语言中需要头文件<stdlib,h>的支持;new/delete是C++的运算符。对于类的对象而言,malloc、free无法满足动态对象的要求。在对象创建的同时要自动执行构造函数,对象消亡之前要自动执行析构函数,而malloc/free不在编译器控制权限之内,无法执行构造函数和析构函数。
具体而言,new/delete与malloc/free的区别主要表现在以下几个方面:
(1)new能够自动计算需要分配的内存空间,而malloc需要手工计算字节数。例如,int* p1=new int[2] , int* p2=malloc(2*sizeof(int))。
(2)new/delete直接带具体类型的指针,malloc/free返回void类型的指针。
(3)new是类型安全的,而malloc不是。例如,int* p=new float[2],编译时就会报错;而int* p=malloc(2*sizeof(float)),编译时编译器就无法指出错误来。
(4)new一般由两步构成,分别是new操作和构造。new操作对应于malloc,但new操作可以重载,可以自定义内存分配策略,不做内存分配,甚至分配到费内存设备上,而malloc不可以。
(5)new将调用构造函数,而malloc不能;delete将调用析构函数,而free不能。
(6)malloc/free需要库文件stdlib.h支持,new/delete则不需要库文件支持。
程序示例如下:
#include "stdafx.h"
#include <iostream>
using namespace std;
class A
{
int i;
public:
A()
{
cout<<"A is here!"<<endl;
}
~A()
{
cout<<"A is dead!"<<endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A* pA=new A;
delete pA;
system("pause");
return 0;
}
此外,需要注意的是:有内存的申请,就必需要有内存的释放,否则就会出现内存泄露的问题,故new/delete、malloc/free必需配对使用。而且,delete或free被调用后,内存不会立即回收,指针也不会指向空,delete或free仅仅是告诉操作系统,这一块内存被释放了,可以被用做其它用途。由于没有重新对这块内存进行写操作,所以内存中的变量数值并没有发生变化,出现野指针的情况(关于野指针的内容,参见博客 http://blog.csdn.net/r77683962/article/details/8189082)。因此,释放完内存后,应该将指针指向置为NULL。
程序示例如下:
#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
void TestDelete()
{
char *str=new char[100];
strcpy(str,"Hello");
delete str;
if(str != NULL)
{
strcpy(str,"World");
cout<<str<<endl;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
TestDelete();
system("pause");
return 0;
}
程序运行的结果如下,但运行时会出现中断。
通过上例可知,delete/free调用后,内存其实并没有立即释放,而且指针本身指向的仍然是这块内存区域,所以在delete/free调用后,还需要将指向该内存的指针置为NULL,防止出现野指针。
最后说一下,既然new/delete的功能完全覆盖了malloc/free,为什么在C++中没有取消掉malloc/free呢?其实,由于C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存,所以仍然保留了malloc/free。