一、mallloc/free 与 new/delete 分配内存差异
1、malloc 是C/C++ 标准库函数; new是C++运算符,同“+-*/”一样。
2、new 分配的是对象,会调用对象的构造函数;malloc 仅分配内存。(操作对象不同)
3、操作差异。
malloc 函数原型:
void * malloc (size_t size);
返回的是 void * 类型,若使用它必须主动进行类型转换。
char* pchr;
//pchr = malloc( sizeof(char) * MAX); //编译不通过
pchr = (char*)malloc( sizeof(char) * MAX);//正确
free 函数原型:
void free(void* memblock);
free释放malloc分配的空间会成功(因事先知道内存大小),若释放之后未置空,再次free则将导致运行出错。free(NULL)则是能正常进行操作。
new 则不需要指定类型。
4、注意 delete 和 free 之后都要将 指针赋空值。漏掉这种操作是导致程序出现野指针的主要原因。
ps:某次看到用 malloc/free 无法满足非内部数据类 动态对象的要求(即自定义类),实际上 placement new 能达到类似的要求,类似于主动调用构造函数。即可先用 malloc 分配地址,然后在起始地址处调用构造函数,不使用对象之后,主动调用 析构函数,如果析构函数中未把申请的动态内存释放完毕, 则需要再调用 free 函数。
二、new,operator new,placement new 说明
new:不能被重载,它先调用 Operator new 分配内存,然后调用构造函数初始化这段内存。
operator new:类似于 operator +/operate -这种。若要实现不同的内存分配行为,应重载operator new,而不是 new。operator delete与delete 类似。delete 首先调用对象的析构函数,然后才调用 operator delete 释放内存。
placement new:operator new 重载的一个版本。本身不分配内存,仅返回指向已分配好的某段内存的一个指针。因此不能删除它,但要调用对象的析构函数。使用placement new 需要添加 #include<new>
placement new 存在的意义:
new 分配数组时,调用默认构造函数,效率不佳,若没有默认构造函数,则发生编译错误。placement new允许在已非配的内存上创建对象;效率高,new操作需要在堆中查找空间,操作速度较慢,且可能出现无法分配的情况,placement 不需要查找内存,适合对时间要求较高,且长时间运行不希望被打断的应用程序。
placement 使用过程:
1、提前分配缓存:①用new、malloc在堆上分配空间;②在栈上分配空间,临时变量;③直接地址
2、对象分配。由1操作获得执行地址的指针 buf,这一步调用 placement new 构造对象:
Obj *pobj = new(buf) Obj;//相当于主动调用类构造函数;
3、使用。像普通对象指针使用 pobj 。
4、对象析构,需要主动调用析构函数:pobj->~Obj();
5、如果是堆区分配的内存,则需要主动释放它:delete/free 等。
三、delete 与 delete[] 注意
delete NULL / delete[] NULL 是可执行通过的。
同时对于内部数据类型,因为不涉及构造函数和析构函数的调用,delete 与 delete [] 操作通用,似乎没有差别;但是对于自定义类型,需要调用构造函数及析构函数时,则需要严格按照 new/delete, new[]/delete[]对应操作来进行。此处有一解释:http://www.360doc.com/content/10/1118/15/1579921_70434158.shtml 。
最后附上一段源码:
代码中最后一段是个测试类大小的Demo,顺便复习一下C++类存储
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <malloc.h>
#include <vld.h>
#include <new>
class CT{
char a;
public:
CT(){
printf_s("Constructor!\n");
}
~CT(){
printf_s("Deconstructor!\n");
}
};
class CVir{
public:
virtual ~CVir();
};
class CIn:public CT,public CVir
{
};
int main()
{
const int MAX = 100;
char mystring[MAX]="Hello my Sweet";
char* pchr;
pchr = (char*)malloc( sizeof(char) * MAX); //编译失败
if ( !pchr )
printf( "malloc failed\n" );
else
{
printf_s("pchr=0x%08x\n", (long)pchr);
strcpy_s(pchr, sizeof(mystring), mystring);
printf_s("%s\n", pchr);
free(pchr);
printf_s("After free!\n");
printf_s("pchr=0x%08x\n", (long)pchr);
pchr =NULL;
}
printf_s("\nBeforeNew pchr=0x%08x\n", (long)pchr);
pchr = new char[MAX];
if (!pchr)
printf( "New failed!\n" );
else
{
printf_s("\np2chr=0x%08x\n", (long)pchr);
strcpy_s(pchr, sizeof(mystring), mystring);
printf_s("%s\n", pchr);
delete [] pchr;
printf_s("After delete[]!\n");
printf_s("p2chr=0x%08x\n", (long)pchr);
pchr =NULL;
delete [] pchr;
printf_s("p2chr=0x%08x\n", (long)pchr);
}
printf_s("\nCT数组分配:\n");
const int Num = 2;
CT* pct = new CT[Num];
//delete pct; //错误,编译通过,执行失败
delete []pct; //正确
printf_s("\nCT单元素分配:\n");
pct =new CT;
//delete[] pct; //错误,编译通过,执行失败
delete pct; //正确
printf_s("\ndelete char数组\n");
pchr = new char[MAX];
delete pchr;
pchr =NULL;
printf_s("\ndelte [] char单元素\n");
pchr = new char;
delete [] pchr;
printf_s("\nPlacement New 演示\n");
printf_s("CT对象大小:%d\n", sizeof(CT));
char* buff[ sizeof(CT) ];
pct = new(buff) CT ;
pct->~CT();
printf_s("CVir对象大小:%d, CIn 对象大小:%d\n", sizeof(CVir), sizeof(CIn));
return 1;
}
运行结果:
完毕