delete 和 delete[] 必须分别匹配 new 和 new[]:单个对象用 delete,数组用 delete[],混用导致未定义行为;释放后应置 nullptr 防悬垂指针;禁对栈变量、字面量或已释放指针重复 delete;优先使用智能指针自动管理内存。

delete 和 delete[] 必须匹配 new 和 new[]
用 new 分配的单个对象,必须用 delete 释放;用 new[] 分配的数组,必须用 delete[] 释放。混用会导致未定义行为——常见表现是程序崩溃、内存泄漏,或看似正常但后续 malloc 失败。
例如:
int* p1 = new int(42); // 单个对象 int* p2 = new int[10]; // 数组 delete p1; // ✅ 正确 delete[] p2; // ✅ 正确 // delete[] p1; // ❌ 危险! // delete p2; // ❌ 危险!
-
delete会调用析构函数(如果类型有),然后释放内存;delete[]会为每个数组元素调用析构函数,再释放整块内存 - 对内置类型(如
int、double)混用可能“暂时不报错”,但仍是错误,不可依赖 - 某些编译器/ASan 在 debug 模式下会检测并报错:
heap-use-after-free或mismatched new/delete
释放后立即置空指针(避免悬垂指针)
释放内存后,原指针仍持有已失效地址,再次解引用就是 segmentation fault 或静默数据损坏。最稳妥做法是释放后立刻赋值为 nullptr。
int* p = new int(100); delete p; p = nullptr; // ✅ 防止二次 delete 或误用 // delete p; // ✅ 安全:delete nullptr 是合法且无操作的
- 即使你确定不会二次释放,也建议置空——多人协作或后续逻辑变更时容易遗漏
- 不置空的情况下,
if (p)判断毫无意义,因为悬垂指针可能非零但已非法 - 注意:只对原始指针有效;智能指针(如
std::unique_ptr)自动管理,无需手动置空
不要对栈变量、字符串字面量或重复释放使用 delete
delete 只能用于由 new 或 new[] 返回的地址。对其他地址调用会直接崩溃。
立即学习“C++免费学习笔记(深入)”;
int x = 42; int* p1 = &x; delete p1; // ❌ segmentation fault —— 栈内存不能 delete <p>const char* s = "hello"; delete[] s; // ❌ 字符串字面量在只读段,不能释放</p><p>int* p2 = new int(1); delete p2; delete p2; // ❌ double free —— 同一地址释放两次
- 编译器通常不检查指针来源,运行时才出错,调试困难
- 重复释放比未释放更危险:可能破坏堆管理元数据,导致后续
malloc或new失败 - 工具如 AddressSanitizer(ASan)可捕获 double-free 和 use-after-free,建议开发期启用
优先用智能指针替代裸指针
手动管理内存极易出错,C++11 起应默认使用 std::unique_ptr 或 std::shared_ptr,它们在离开作用域时自动释放,且禁止拷贝(unique_ptr)或带引用计数(shared_ptr)。
auto p1 = std::make_unique<int>(42); // 自动管理,无需 delete
auto p2 = std::make_unique<int[]>(10); // 对应 new[],自动用 delete[]
<p>{
auto p3 = std::make_shared<std::string>("test");
} // p3 离开作用域,string 自动析构、内存自动释放-
std::make_unique和std::make_shared更安全:异常安全、避免裸new后忘记初始化 - 数组场景下,
std::unique_ptr<int></int>显式表明是数组类型,编译器会选delete[] - 唯一例外是和 C API 交互(如
malloc+free)或性能极端敏感的底层代码,否则裸指针应视为遗留写法
实际项目里最容易被忽略的不是语法是否正确,而是「谁负责释放」——尤其在函数返回裸指针、跨模块传递或异常路径中。一旦涉及多个作用域或条件分支,手动 delete 几乎必然漏掉。智能指针不是银弹,但能消除绝大多数人为疏忽。


















