c++oding="utf-8" ?>
最核心区别是new调用构造函数而malloc不调用,导致c++对象未初始化、处于未定义状态;new类型安全、异常处理,malloc需手动转换与判空;delete与free绝不可混用。

别用 malloc 给 C++ 对象分配内存,这是最核心的判断。它不调用构造函数,对象处于未定义状态,后续任何成员访问或析构都是未定义行为。
new 会调用构造函数,malloc 不会
这是最致命的区别,不是风格差异,而是语义鸿沟。
-
malloc只返回一块原始字节区域,哪怕你给它传了sizeof(MyClass),MyClass的构造函数也完全不会执行;成员变量是垃圾值,内部资源(如指针、文件句柄)没初始化,对象根本“活”不起来 -
new的完整流程是:先调用operator new分配内存(底层可能用malloc实现),再在该地址上执行MyClass::MyClass();整个过程原子化,失败就抛std::bad_alloc,不会留下半初始化对象 - 反例:
MyClass* p = (MyClass*)malloc(sizeof(MyClass)); p->do_something();—— 极大概率崩溃,因为p->do_something()可能依赖未初始化的成员
类型安全与强制转换风险
malloc 返回 void*,必须手动强转;new 返回精确类型指针,编译器全程检查。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 强转掩盖错误:
int* p = (int*)malloc(sizeof(double));编译通过,但后续写入 8 字节会踩坏相邻内存 - 类型不匹配难发现:
char* buf = (char*)malloc(100); MyClass* obj = (MyClass*)buf;—— 指针类型变了,但编译器不报错,运行时才暴露问题 -
new天然杜绝这类问题:MyClass* obj = new MyClass;类型由编译器推导并校验,错配直接编译失败
异常 vs 返回 NULL,错误处理路径完全不同
混用两套错误处理逻辑,极易引入空指针解引用或漏捕获异常。
-
malloc失败返回NULL,你必须显式判空:if (!p) { /* handle error */ } -
new默认失败抛std::bad_alloc,不返回NULL;写if (p == nullptr)完全无效,且掩盖了异常路径 - 若坚持用
NULL风格,可用new(std::nothrow):int* p = new(std::nothrow) int[1000]; if (!p) { /* handle fail */ },但这样就放弃了 C++ 异常机制的优势
delete 和 free 不能交叉释放
内存来源决定释放方式,跨用必崩。
- 用
malloc分配的内存,必须用free释放;用new分配的,必须用delete或delete[]释放 - 常见错误:
int* p = new int[10]; free(p);——free不知道这是数组,不会调用多个析构函数(虽内置类型无影响),且可能因元数据结构不同导致堆损坏 - 更隐蔽的是重载场景:若类重载了
operator new,其配套的operator delete可能有特殊逻辑(如内存池回收),用free直接绕过,资源永远泄漏
真正容易被忽略的点是:即使你只操作 int、double 这类 POD 类型,malloc/free 和 new/delete 在 ABI 层面的内存块元数据格式也可能不同。glibc 的 malloc 和 libstdc++ 的 operator new 管理空闲链表的方式独立,交叉释放极大概率触发 malloc(): unaligned tcache chunk detected 这类崩溃。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










