1. 类型安全性和返回类型
new:是 C++ 的关键字,自动推导类型,返回指定类型的指针。由于new知道要分配的对象类型,它是类型安全的,且不需要强制类型转换。
int* p = new int(10);  // 自动返回 int* 类型,无需强制转换 
malloc:是 C 库函数,需要手动指定分配的字节数,返回void*类型,因此通常需要显式类型转换,以匹配目标指针类型。它是类型不安全的,因为它只知道分配内存的大小,不知道分配的具体类型。
int* p = (int*)malloc(sizeof(int));  // 需要强制类型转换 
2. 内存分配和对象初始化
new:不仅仅分配内存,它还会调用构造函数来初始化对象。如果是基础类型,如int、float,new允许你直接赋值。
MyClass* obj = new MyClass();  // 分配内存并调用构造函数
int* p = new int(10);  // 分配内存并将 10 赋值给该地址 
malloc:只负责分配原始内存,不会调用构造函数,也不会进行初始化。对于对象类型,如果你需要初始化对象,必须手动调用构造函数。
MyClass* obj = (MyClass*)malloc(sizeof(MyClass));  // 仅分配内存,不调用构造函数 
3. 内存释放和对象销毁
new:与new相对应的释放内存操作是delete。delete不仅释放内存,还会调用析构函数,从而保证对象的资源正确释放(如关闭文件、释放动态分配的内存等)。
delete p;       // 释放单个对象,调用析构函数
delete[] p;     // 释放数组对象,调用每个元素的析构函数 
malloc:与malloc相对应的释放内存操作是free()。free()只会释放内存,不会调用析构函数。如果对象持有资源(如动态内存或文件句柄),这些资源将不会被正确释放,可能导致内存泄漏或资源泄漏。
free(p);  // 仅释放内存,不调用析构函数 
4. 分配数组
new[]:可以用于动态分配对象数组。它分配内存并为数组中的每个对象调用构造函数。当使用delete[]释放数组时,每个对象的析构函数都会被调用。
int* arr = new int[10];  // 分配一个包含 10 个 int 的数组
delete[] arr;            // 使用 delete[] 来释放数组 
malloc:用于分配任意大小的内存块,包括数组,但它并不知道内存块的元素类型,也不会调用构造函数和析构函数。手动管理数组的初始化和释放非常复杂。
int* arr = (int*)malloc(10 * sizeof(int));  // 分配 10 个 int 大小的内存
free(arr);                                  // 释放内存,不调用析构函数 
5. 异常处理
new:如果内存分配失败,new会抛出std::bad_alloc异常,这使得处理内存分配失败更加方便。
try {int* p = new int[1000000000];  // 分配大量内存
} catch (std::bad_alloc& e) {std::cerr << "Memory allocation failed: " << e.what() << std::endl;
} 
malloc:如果内存分配失败,malloc返回NULL,你必须手动检查返回值来处理错误。这种方法不如new的异常处理机制方便。
int* p = (int*)malloc(1000000000 * sizeof(int));
if (!p) {std::cerr << "Memory allocation failed" << std::endl;
} 
6. 可重载性
new:可以在类中重载new和delete操作符,以控制特定类的内存分配方式。
class MyClass {
public:void* operator new(size_t size) {std::cout << "Custom new operator" << std::endl;return ::operator new(size);  // 调用全局 new}void operator delete(void* ptr) {std::cout << "Custom delete operator" << std::endl;::operator delete(ptr);  // 调用全局 delete}
}; 
malloc:是标准库函数,无法被重载。
7. 语言特性
new是 C++ 的语言级别操作符,支持对象的构造与析构。malloc是 C 语言中的标准库函数,只能分配内存,不支持类的构造与析构。
总结:
|   特性  |   
  |   
  | 
|   返回类型  |   返回类型安全的指针  |   返回   | 
|   初始化  |   调用构造函数并初始化  |   仅分配内存,不初始化  | 
|   释放内存  |   
  |   
  | 
|   异常处理  |   内存不足时抛出   |   内存不足时返回   | 
|   数组分配  |   支持   |   分配内存块,不关心类型  | 
|   可重载性  |   可以在类中重载  |   无法重载  | 
        在 C++ 中,new 更适合分配和管理对象,因为它支持构造函数和析构函数的自动调用。而 malloc 更适用于与 C 代码的兼容性场景中,只负责内存分配,不关心对象的初始化和销毁。
