文章

对比malloc-free与new-delete

对比malloc-free与new-delete

对比malloc-free与new-delete

malloc/freenew/delete 是 C++ 中两种动态内存分配和释放的机制,分别源自 C 和 C++ 语言。它们在底层实现、用途、语义和使用场景上有显著差异。

一、基本语法和用途

功能malloc / freenew / delete
来自语言CC++
头文件<stdlib.h>无需头文件(是 C++ 的关键字)
分配语法void* p = malloc(size)T* p = new T(...)
释放语法free(p)delete p
数组分配int* a = malloc(n * sizeof(int))int* a = new int[n]
数组释放free(a)delete[] a

二、核心区别对比

对比点malloc / freenew / delete
是否调用构造/析构函数❌ 不调用构造函数和析构函数✅ 调用构造函数分配对象,调用析构函数释放对象
返回类型void*,需强制类型转换类型安全,不需要类型转换
失败处理返回 NULL抛出 std::bad_alloc 异常(除非使用 new (nothrow)
自定义分配器不能重载可以通过重载 operator newoperator delete 实现自定义分配器
灵活性可以方便地实现复杂的内存池等机制更面向对象,适合常规对象的创建和销毁
语义层面只是字节分配器,和类型无关是对象创建工具,包含初始化和类型语义

三、举例说明

  1. 使用 malloc 分配结构体(不会调用构造函数):
1
2
3
4
5
6
7
struct Person {
    Person() { std::cout << "Constructor\n"; }
    ~Person() { std::cout << "Destructor\n"; }
};

Person* p1 = (Person*)malloc(sizeof(Person)); // 不会调用构造函数
free(p1);                                     // 不会调用析构函数
  1. 使用 new 分配结构体(会调用构造函数):
1
2
Person* p2 = new Person(); // 会调用构造函数
delete p2;                 // 会调用析构函数

四、底层机制差异

项目malloc/freenew/delete
底层函数通常调用 brk/sbrkmmap底层依赖于 operator new(),最终可能也是 malloc
自定义重载无法重载 malloc/free可以通过重载 operator new/delete 实现
内存对齐平台相关(现代实现如 jemalloc 会处理)C++ 编译器一般会处理好对齐问题

五、何时使用哪种

场景建议使用原因
面向对象编程new/delete自动调用构造/析构,类型安全
C 风格代码/底层内存池malloc/free更加灵活,可以与 memcpy/realloc 等结合使用
STL 容器内部分配new/deleteSTL 默认使用 allocator,底层使用 ::operator new
自定义内存管理器malloc/free 或更底层可直接操作字节,对象语义无关
希望处理失败情况new (nothrow) 或检查 malloc 返回值分别适用于异常/非异常

六、placement new

placement new 是 C++ 中的一种 内存构造技术,允许在指定的内存地址上构造对象,而不是通过 new 自动分配内存再构造对象。

普通 new

1
T* p = new T(args); // 分配内存 + 调用构造函数

placement new

1
2
void* buffer = malloc(sizeof(T));  // 你手动分配了内存
T* p = new (buffer) T(args);       // 在指定内存上“就地构造”对象

关键点new (地址) 类型placement new 的语法,它只做“构造”,不会分配内存。

适用场景

  • 内存池(memory pool)
  • 对象重用(避免频繁 new/delete)
  • 嵌入式开发(精细控制内存)
  • 需要在某块预分配的内存中构造对象
特性普通 newplacement new
内存分配✅ 自动分配❌ 你自己分配
构造函数调用✅ 自动调用✅ 自动调用
析构函数调用✅ 自动调用(在 delete 时)❌ 需手动调用
用途一般对象创建自定义内存管理、内存池等高级用途
本文由作者按照 CC BY 4.0 进行授权