1. new/delete与malloc/free的区别
1.1 相同点
- 在C++中,动态申请内存和释放内存,用new/delete和malloc/free都可以,并且它们的存储方式都一样,都是在堆上申请,且无法被操作系统释放,只能由程序员用delete和free来进行释放
- 对于内置数据类型,如int、char类型,使用malloc和new的效果是一样的
1.2 不同点
- new/delete是C++的运算符,而malloc/free是C/C++语言的标准库函数
- 对于类的对象而言,malloc/free无法满足动态对象的要求,对象在创建的同时需要调用构造函数,对象在销毁的同时需要调用析构函数,因为malloc/free不在编译器的控制权限之内,无法执行构造函数析构函数
1.3 总结
比较项 | new/delete | malloc/free | 举例说明 |
---|---|---|---|
是否需要手动计算申请大小 | new能自动计算分配的内存空间 | 需要手动计算 | int *p1 = new int[2]; int *p2 = (int *) malloc(2*sizeof(int)) |
是否带具体类型的指针 | new申请之后自动转为称申请数据类型的指针 | 返回void *类型指针,需要进行强制转化 | N/A |
是否类型安全 | new是类型安全 | malloc不安全 | int *p2 = new float[2]; 会在编译时报错;int *p2 = (int *)malloc(2*sizeof(float)) ,编译器不会报错 |
类类型的对象 | new调用构造函数,delete调用析构函数 | malloc不调用析构函数,free不调用析构函数 | N/A |
是否需要库文件的支持 | new/delete不需要 | malloc/free需要 | malloc/free需要库文件stdlib.h文件 |
1.4 代码展示
new/delete代码展示
#include <iostream>
using namespace std;
class A{
public:
A(){
cout << "A Constructor ..." << endl;
}
~A(){
cout << "A Destructor ..." << endl;
}
void printHello(){
cout << "Hello World" << endl;
}
};
/* C++的new默认是没有返回值的,会抛出异常,那么如何判断new是否成功
* 1. 通过try...catch捕获异常的方式
* 2. 强制让new不抛异常,而是真正有返回值
*/
int main(){
// new不抛异常版本,这样就可以通过返回值来判断是否成功
A * ptrA = new (std::nothrow)A();
if(nullptr == ptrA) return -1;
delete ptrA;
/* delete和free被调用后,内存不会立即被收回,指针也不为空,只是告诉系统该内存可以另作他用
* 如果这块内存没有被另作它用,内存中的数据也不会发生变化,会出现野指针的情况
* ptrA->printHello(); 这句代码展示了delete后的指针还可以继续访问printHello()函数
* 所以,内存被释放后应该立即将该指针置为空指针 ptrA == nullptr;
*/
ptrA->printHello();
return 0;
}
malloc/free代码展示
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void testFree(){
char * str = (char *)malloc(100);
if(NULL == str) return ;
strcpy(str, "Hello");
printf("%s\n", str);
free(str);
/*
* 以下的这个if语句块可以看书,指针free之后内存并没有立即被释放
* 正确的姿势是在调用free之后,需要将指针置空, str = NULL
*/
if (NULL != str){
strcpy(str, "World");
printf("%s\n", str);
}
return ;
}
int main(){
testFree();
return 0;
}
1.5 后语
此时便产生了一个疑问,既然new/delete的功能完全覆盖了malloc/free,为什么C++中没有取消掉malloc/free,而是继续保留呢? 原因是C++经常要调用C函数,而C语言只有malloc/free管理动态内存,所以保留了malloc/free