new的几种形式
C++ 中的 new
操作符实际上有多种形式,根据使用方式和功能可分为如下几类:
✅ 一、基本形式
1. 普通单对象分配
MyClass* p = new MyClass(); // 默认构造
MyClass* p2 = new MyClass(123); // 调用带参构造函数
2. 数组形式
MyClass* arr = new MyClass[10]; // 分配并构造 10 个默认构造的对象
必须配对使用
delete[]
,否则只析构第一个对象!
✅ 二、带 nothrow
的安全形式(避免异常)
MyClass* p = new(std::nothrow) MyClass();
if (!p) {// 分配失败,不抛异常,返回 nullptr
}
适用于资源有限、不能容忍异常的系统(如嵌入式设备)。
✅ 三、Placement new(定址构造)
在已有内存上构造对象,常用于自定义内存池、共享内存等场景。
void* buffer = malloc(sizeof(MyClass));
MyClass* p = new (buffer) MyClass(123); // 定址构造
注意:
-
不会分配内存,只调用构造函数;
-
析构必须显式调用:
p->~MyClass();
✅ 四、重载版本(类或全局)
你可以重载 operator new
来控制分配行为:
void* MyClass::operator new(std::size_t size) {std::cout << "custom new\n";return ::operator new(size);
}
void MyClass::operator delete(void* ptr) {std::cout << "custom delete\n";::operator delete(ptr);
}
还可以写成 全局重载版本,或接受额外参数用于调试/分区管理。
✅ 五、对齐版本(C++17 起)
struct alignas(64) AlignedClass {int data;
};AlignedClass* p = new AlignedClass(); // 自动 64 字节对齐
也可以自定义重载如下:
void* operator new(std::size_t size, std::align_val_t align);
✅ 六、数组 + Placement + 对齐的组合形式(不推荐混用)
可以组合使用,如:
void* mem = malloc(sizeof(MyClass) * 10);
MyClass* arr = new (mem) MyClass[10]; // 错误!数组不能用 placement new 这样构造!
new T[n]
和placement new
不兼容数组构造,要显式循环手动构造:
for (int i = 0; i < 10; ++i)new (static_cast<void*>(mem) + i * sizeof(MyClass)) MyClass();
🔁 全部形式简表
形式 | 示例 | 特点 |
---|---|---|
普通 new | new MyClass(1) | 分配 + 构造 |
普通 new[] | new MyClass[10] | 构造多个对象 |
nothrow new | new(std::nothrow) MyClass() | 分配失败返回 nullptr ,不抛异常 |
Placement new | new (ptr) MyClass(1) | 在已有地址构造,不分配内存 |
自定义重载 operator new | MyClass::operator new(...) | 控制分配策略 |
对齐 new(C++17) | new (std::align_val_t(64)) MyClass() | 用于 SIMD / 硬件对齐需求 |
数组 + 对齐 new(复杂慎用) | new (std::align_val_t(64)) MyClass[10] | 实现复杂,通常不推荐 |
✅ 总结一句话:
C++ 中
new
不只是“分配内存”,它是类型感知的对象创建机制,支持构造、析构、对齐和自定义行为,远比malloc
灵活强大。