new和malloc的区别
从表层调用来看:
1. 名称/语法
一个是操作符,一个是调用函数(cdecl)
int *v1 = new int;//无需指定内存块的大小
int *v2 = (int*)malloc(sizeof(int));//需显式指出内存块的大小
delete v1;
free(v1);
2. 申请内存
动态申请内存时,对于类的实例化对象,new/delete会调用对象的构造函数/析构函数以完成对象的构造/析构。而malloc则不会
new操作符分配对象内存:
- 调用operator new 函数(对于数组是operator new[])分配一块足够大的,原始的,未命名的内存空间以便存储特定类型的对象。
- 编译器运行相应的构造函数以构造对象,并为其传入初值。
- 对象构造完成后,返回一个指向该对象的指针。
delete操作符释放对象内存:
- 调用对象的析构函数。
- 编译器调用operator delete(或operator delete[])函数释放内存空间。
3. malloc调用的是进程默认堆,而new既可以调用进程默认堆,又可以调用自定义堆
特征 | new/delete | malloc/free |
---|---|---|
分配内存的位置 | 自由存储区 | 堆 |
内存分配返回值 | 完整类型指针 | void* |
内存分配失败返回值 | 默认抛出bac_alloc异常 | 返回NULL |
分配内存的大小 | 由编译器根据类型计算得出 | 必须显式指定字节数 |
处理数组 | 有处理数组的new版本new[] | 需要用户计算数组的大小后进行内存分配 |
已分配内存的扩充 | 无法直观地处理 | 使用realloc简单完成 |
是否相互调用 | 可以,看具体的operator new/delete实现 | 不可调用new |
分配内存时内存不足 | 客户能够指定处理函数或重新制定分配器 | 无法通过用户代码进行处理 |
函数重载 | 允许 | 不允许 |
构造函数与析构函数 | 调用 | 不调用 |
从源码的底层实现来看,两者并无差别
1. new/delete
new->LocalAlloc->RtlAllocateHeap
delete->LocalFree->GlobalFree->RtlFreeHeap
2. malloc/free
malloc->RtlAllocateHeap
free->RtlFreeHeap