重载全局 operator new 仅拦截普通 new 表达式,不处理 placement new;必须显式定义 operator new(size_t, void*) 才能接管 placement 场景,且 operator new 与 operator delete 必须严格成对重载以确保正确释放。

重载全局 operator new 会拦截所有 new 表达式,但不处理 placement new
只要你定义了非 placement 版本的 operator new,它就会被所有不带额外参数的 new 调用(比如 new int、new MyClass())自动选用。但注意:new (ptr) T 这种 placement 形式完全绕过你的重载,它只调用 operator new(size_t, void*) —— 如果你没定义这个版本,就直接用系统默认的,不会报错也不会走你的逻辑。
常见错误现象:
• 自定义 operator new 里加了日志或统计,结果 placement new 分配时完全没输出
• 以为统一控制了内存分配,实际部分对象逃逸了监控
- 必须显式定义
operator new(size_t, void*)才能接管 placement 场景 - 这个函数通常只返回传入的
void*指针,不做实际分配 - 如果忘记定义,链接期不会报错,运行时行为符合标准但可能不符合预期
operator new 和 operator delete 必须成对重载,否则析构后内存无法回收
C++ 要求:每个自定义的 operator new 都应有对应签名的 operator delete。不是“写了就行”,而是“调用哪个 new,就必须由匹配的 delete 处理”。否则对象析构后,delete 可能调用系统默认版本,导致释放到错误堆、崩溃或静默损坏。
使用场景:
• 用自定义 operator new(size_t, Pool&) 分配对象
• 析构后若只重载了全局 operator delete(void*),而没写 operator delete(void*, Pool&),就会出问题
立即学习“C++免费学习笔记(深入)”;
- 编译器根据
new表达式使用的参数列表,决定调用哪个operator delete - 即使
operator new抛异常,C++ 也会尝试调用匹配的operator delete做清理(前提是它存在) - 类内重载时,
operator delete必须是static,且签名要与对应new严格一致
类内重载 operator new 优先级高于全局,但不继承、不参与 ADL
如果在某个类(比如 class A)里定义了 static void* operator new(size_t),那么 new A 一定调用它,不管全局有没有定义。但子类 B : public A 不会自动获得这个能力 —— C++ 明确规定类内重载不继承。
性能 / 兼容性影响:
• 类内版本避免虚函数开销,适合高频小对象(如节点类)
• 但和智能指针(如 std::shared_ptr)配合时需小心:shared_ptr 默认用全局 operator delete,除非你显式传入自定义删除器
- 类内重载的
operator new对new A[10]无效 —— 数组形式需要单独重载operator new[](size_t) - 模板类中重载,每个实例化类型(如
Vec<int></int>、Vec<double></double>)都生成独立版本 - 不能依赖 ADL 查找:即使
operator new定义在类所在命名空间,全局new X也不会去那里找,除非是类内定义
重载 operator new 后,std::allocator 和容器完全不受影响
std::vector、std::string 等标准容器默认用 std::allocator,而它内部调用的是 ::operator new(即全局版本)。所以如果你只重载了某个类的成员 operator new,或者只重载了特定命名空间下的版本,容器分配内存时根本不会感知。
常见错误现象:
• 以为重载了全局 operator new 就能监控 vector.push_back() 的每次扩容
• 实际上只要没动 ::operator new,容器就走 libc 的 malloc
- 想让容器走自定义分配,必须传入自定义
Allocator模板参数,例如std::vector<int myalloc>></int> - 重载全局
::operator new确实会影响容器,但它也会影响所有其他代码(包括第三方库),风险高、调试难 - 某些 STL 实现(如 libstdc++)在 debug 模式下会额外检查分配器一致性,此时 mismatch 的
new/delete可能触发断言
重载 operator new 看似只是换一个函数,但它的调用路径、匹配规则、生命周期责任都紧耦合在 C++ 对象模型底层。最容易被忽略的是:析构后的 operator delete 必须和构造前的 operator new 严格配对,差一个参数、少一个重载,就可能埋下释放未分配内存或跳过自定义回收逻辑的隐患。









