卡码笔记-最强八股文
首页
计算机基础
C++
Java
Go
🔥大模型🔥
  • 大模型面经
  • Java面经
  • C++面经
简历专栏
代码随想录 (opens new window)
首页
计算机基础
C++
Java
Go
🔥大模型🔥
  • 大模型面经
  • Java面经
  • C++面经
简历专栏
代码随想录 (opens new window)
  • 本栏必读

    • 关于本专栏
    • C++学习路线
    • C++面试题系优化
  • 基础与语法

  • 面向对象

  • STL 与容器

  • 内存管理

    • C++内存分区,堆和栈的区别
    • new和melloc的区别是什么?
      • 简要回答
      • 详细回答
      • 知识拓展
    • free和delete区别的是什么?
    • placement new的作用
    • 什么是内存泄漏?什么是野指针?什么是内存越界?如何避免?
    • 内存碎片与内存溢出
    • 如何避免内存碎片
  • C++11 与现代 C++

  • 智能指针

  • 并发与 I/O

# new 和 malloc 的区别

面试官问"new 和 malloc 有什么区别",很多人能列出几条差异,但追问"new 的底层调用链路是什么""placement new 怎么用""delete[] 为什么不能用 delete 替代"就答不清楚了。这道题的核心是理解:new 做了两件事(分配内存 + 调构造),malloc 只做一件事(分配内存)。

# 简要回答

new 是 C++ 运算符,一次操作完成两件事:先通过 operator new 分配内存,再在这块内存上调用构造函数初始化对象。malloc 是 C 标准库函数,只负责分配一块指定大小的原始内存,不调用任何构造函数。对应地,delete 先调析构再释放内存,free 只释放内存不调析构。new 失败抛 bad_alloc 异常,malloc 失败返回 NULL。new 返回具体类型指针(类型安全),malloc 返回 void* 需要强转。

# 详细回答

new 做了什么

new MyClass(10) 这一行代码,编译器实际上拆成两步:第一步调用 operator new(sizeof(MyClass)) 分配内存——这个函数内部通常就是调 malloc;第二步在分配到的内存地址上调用 MyClass 的构造函数。所以 new 的完整调用链路是:new → operator new → malloc → mmap/brk(操作系统底层)。

对应地,delete obj 也是两步:先调用 obj->~MyClass() 析构函数,再调用 operator delete(obj) 释放内存(内部通常调 free)。

malloc 做了什么

malloc(sizeof(MyClass)) 只做一件事:向操作系统申请一块指定大小的原始内存,返回 void* 指针。这块内存里是垃圾值,没有任何初始化。你不能在 malloc 返回的内存上直接当对象用——成员变量没初始化,虚函数表指针没设置,行为是未定义的。

对应地,free(obj) 只释放内存,不调用析构函数。如果对象持有堆内存(比如 string 成员),直接 free 会导致内存泄漏。

其他关键差异

new 不需要手动计算大小(编译器自动算 sizeof),malloc 必须手动传大小参数。new 可以被类重载(自定义内存池),malloc 不能重载。new[] 分配数组时会额外记录元素个数,delete[] 根据这个数字批量调析构;如果用 delete 代替 delete[],只会析构第一个元素,剩下的全部泄漏。

new与malloc调用链路对比

# 知识拓展

Q:能不能用 malloc 分配内存后手动调构造函数?

可以,用 placement new:MyClass* obj = new (mem) MyClass(10);,其中 mem 是 malloc 返回的指针。placement new 不分配内存,只在指定地址上调构造函数。析构时也要手动调 obj->~MyClass(),然后再 free(mem)。内存池就是这么实现的。

Q:new 的底层一定调 malloc 吗?

不一定。operator new 的默认实现通常调 malloc,但你可以重载 operator new 用自己的分配器(比如从内存池分配)。标准只要求 operator new 返回一块足够大的对齐内存,不规定底层实现。

Q:什么时候该用 malloc 而不是 new?

和 C 代码交互时(C 没有 new);分配 POD 类型的原始内存块(比如网络缓冲区 char*);实现自定义内存分配器时。现代 C++ 中,绝大多数场景应该用 new(或者更好的选择:智能指针 + make_shared/make_unique),只有底层系统编程才需要 malloc。

Q:delete[] 为什么不能用 delete 替代?

new[] 分配数组时,编译器会在内存块头部多分配几个字节记录元素个数 N。delete[] 读取这个 N,然后循环调用 N 次析构函数,最后释放整块内存。如果用 delete 代替,它只调用一次析构(第一个元素),剩下 N-1 个元素的析构函数不会被调用,资源泄漏。对于 POD 类型(没有析构函数)混用不会崩溃,但属于未定义行为,不要这么做。

Last Updated: 5/23/2026, 4:51:07 PM

← C++内存分区,堆和栈的区别 free和delete区别的是什么? →

评论

验证登录状态...

侧边栏 侧边栏
夜间模式 夜间
卡码简历 卡码简历
代码随想录 代码随想录
卡码投递表 卡码投递表🔥
2026实习校招群 2026群
添加客服微信 2026实习校招客服微信 PS:通过微信后,请发送姓名-学校-年级-2026实习/校招
支持卡码笔记 支持卡码笔记
鼓励/支持/赞赏Carl 卡码笔记赞赏码
1. 如果感觉本站对你很有帮助,也可以请Carl喝杯奶茶,金额大小不重要,心意已经收下
2. 希望大家都能梦想成真,有好的前程,加油💪