new表达式执行三步:调用operator new分配原始内存、在该内存上调用构造函数、返回类型化指针;operator new仅分配内存,不调构造函数,可重载;placement new只调构造函数,不分配内存。

operator new 是函数,new 表达式是语言内置操作符;前者只管分配原始内存,后者负责分配 + 构造 + 返回类型化指针。
new 表达式(new operator)到底做了什么
写 MyClass* p = new MyClass(42); 这行代码时,编译器实际执行三步:
- 调用
operator new(sizeof(MyClass))分配一块未初始化的内存 - 在该内存地址上调用
MyClass::MyClass(42)构造函数 - 把这块已构造好的内存地址转成
MyClass*类型并返回
这整个过程封装在 new 关键字里,不可重载、不可拆解——它就是 C++ 语法的一部分。你不能改它的行为,只能影响它调用的 operator new。
operator new 只做一件事:要内存,不碰对象
operator new 的标准签名是 void* operator new(std::size_t),它和 malloc 非常像:
立即学习“C++免费学习笔记(深入)”;
- 输入是字节数,输出是
void*,不带任何类型信息 - 不调用构造函数,也不关心你要放什么对象
- 失败时默认抛
std::bad_alloc,加std::nothrow可改为返回nullptr - 可以被全局重载或类内重载,比如用于内存池、日志跟踪、对齐控制
典型误用:直接用 operator new 分配内存后,忘了手动调用构造函数,就当对象用了——这时访问成员会触发未定义行为。
为什么不能混用 operator new 和 delete 表达式
用 operator new 分配的内存,必须配对使用 operator delete 释放,而不是 delete 表达式:
-
void* raw = operator new(1024);→ 合法 -
delete raw;→ 错误!delete表达式会先尝试调用析构函数(但raw不是指向对象的指针),再调operator delete,行为未定义 -
operator delete(raw);→ 正确,只归还内存
更隐蔽的坑:如果你重载了类的 operator new,但没同时重载对应的 operator delete,那么用 new MyClass 分配的对象在 delete 时可能调用默认的全局 operator delete,导致内存管理逻辑错位。
placement new 是个特例,但它不是 operator new 的重载
new (ptr) MyClass() 这种写法叫 placement new,它不分配内存,只调构造函数。关键点:
- 它底层调用的是一个特殊的
operator new重载:void* operator new(std::size_t, void* p),这个版本只是原样返回p - 这个重载不可自定义实现逻辑(标准禁止你改它),你也不能把它声明为类成员
- 用完后不能用
delete,必须显式调用析构函数:p->~MyClass(),再按需释放底层内存
真正容易被忽略的是:placement new 的存在,让「分配」和「构造」彻底解耦——这是 std::vector、std::string 等容器能高效预分配又延迟构造的根本机制。没理解这点,就很难看懂它们的源码。


















