new和delete是C++内置操作符,非函数,只能重载operator new/delete而非其本身;必须严格配对使用,数组用new[]/delete[],单对象用new/delete,混用导致未定义行为;推荐RAII智能指针或容器替代裸指针。

new 和 delete 是 C++ 原生内存管理操作符,不是函数
它们直接调用全局 operator new 和 operator delete 函数,但语义上属于语言内置机制。这意味着你不能重载 new 或 delete 本身,只能重载底层的 operator new(比如 void* operator new(size_t))。
常见错误是把 new 当成普通函数来写括号——new(int) 是错的,正确写法是 new int;数组形式必须用方括号:new int[10],不能写成 new(int[10])。
-
new T分配单个对象,返回T*;new T[n]分配数组,返回T*(注意:不是T**) - 分配失败时,
new默认抛出std::bad_alloc异常;若想返回nullptr,得用new(std::nothrow) T -
delete p只能用于new返回的指针;delete[] p只能用于new[]返回的指针;混用会导致未定义行为(常见崩溃或内存泄漏)
为什么 delete 和 delete[] 不能互换
编译器在 new[] 时通常会在实际分配的内存块前额外写入数组长度(具体实现依赖编译器),delete[] 会读取这个信息来决定调用几次析构函数。而 delete 不读这个头,只调用一次析构函数,其余对象的析构被跳过,资源不释放。
对内置类型(如 int、double)看似“没影响”,但这只是侥幸——一旦涉及类类型(比如 std::string 数组),漏掉析构就会导致严重资源泄漏。
立即学习“C++免费学习笔记(深入)”;
- 用
new int[5]→ 必须用delete[] p - 用
new std::string[3]→ 必须用delete[] p,否则三个std::string的内部缓冲区不会释放 - 没有语法能从指针反推它来自
new还是new[],所以责任完全在程序员
new/delete 容易踩的坑:裸指针 + 异常 = 内存泄漏
如果 new 后面的代码抛异常,而你没做异常安全处理,delete 就永远不会执行。
int* p = new int[1000]; do_something_that_might_throw(); // 若这里 throw,p 就泄露了 delete[] p; // 这行根本跑不到
解决方案不是靠人盯住每处 new 配 delete,而是用 RAII:
- 优先用
std::vector替代new int[n] - 用
std::unique_ptr管理单个对象:auto p = std::make_unique(42); - 用
std::unique_ptr管理数组:auto p = std::make_unique(100); - 除非写底层库或性能敏感路径,否则避免裸
new/delete
自定义类型中重载 operator new/delete 的真实用途
重载 operator new 主要用于内存池、调试追踪或对齐控制,不是为了“替换 malloc”。例如:
class MyClass {
public:
void* operator new(size_t size) {
return aligned_alloc(64, size); // 强制 64 字节对齐
}
void operator delete(void* ptr) noexcept {
free(ptr);
}
};
注意点:
- 重载的
operator new必须返回void*,且不能有返回值检查逻辑(异常由它自己抛) - 匹配的
operator delete必须声明为noexcept,否则析构异常时可能二次崩溃 - 类内重载只影响该类对象的
new,不影响其成员或基类;全局重载影响所有类型(慎用) - 重载不改变
new[]/delete[]的行为——它们调用的是独立的operator new[]和operator delete[]
真正需要手动管理内存的地方不多,多数时候问题不在“怎么用 new”,而在“为什么不用 vector 或 unique_ptr”。










