文章

对比malloc-free与new-delete

malloc/free 仅分配与释放内存,需手动构造对象;new/delete 除内存管理外还调用构造与析构,更适合 C++ 面向对象编程。

对比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

核心区别

  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
是否调用构造/析构函数不调用构造函数和析构函数调用构造函数分配对象,调用析构函数释放对象
返回类型void*,需强制类型转换类型安全,不需要类型转换
失败处理返回 NULL抛出 std::bad_alloc 异常(除非使用 new (nothrow)
底层函数通常调用 brk/sbrkmmap底层依赖于 operator new(),最终可能也是 malloc
自定义分配器不能重载可以通过重载 operator newoperator delete 实现自定义分配器
灵活性可以方便地实现复杂的内存池等机制更面向对象,适合常规对象的创建和销毁
语义层面只是字节分配器,和类型无关是对象创建工具,包含初始化和类型语义
内存对齐平台相关(现代实现如 jemalloc 会处理)C++ 编译器一般会处理好对齐问题

使用场景

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

定位 new

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

普通 new:

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

定位 new:

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

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

适用场景

  • 内存池(memory pool)
  • 对象重用(避免频繁 new/delete)
  • 嵌入式开发(精细控制内存)
  • 需要在某块预分配的内存中构造对象
本文由作者按照 CC BY 4.0 进行授权