析构函数中必须用 delete[] 释放 new[] 分配的数组,否则导致未定义行为;应优先使用 std::vector 或 std::unique_ptr<int[]> 避免手动管理,且 delete[] 对空指针安全。

析构函数里用 delete[] 释放 new[] 分配的数组
必须严格配对:用 new[] 分配的内存,只能用 delete[] 释放。用 delete(不带方括号)释放会导致未定义行为——常见表现是程序崩溃、内存泄漏或静默损坏堆结构。
典型错误写法:
class Buffer {
int* data;
public:
Buffer(int n) : data(new int[n]) {}
~Buffer() { delete data; } // ❌ 错!应为 delete[]
};- 如果数组元素是自定义类型,
delete[]会自动调用每个元素的析构函数;delete只调用第一个元素的析构函数,其余跳过 - 编译器通常无法在编译期检查这个错误,运行时才出问题,排查困难
- 现代 C++ 中优先用
std::vector或std::unique_ptr<T[]>,从根本上规避手动管理
别在析构函数里释放栈数组或全局数组
析构函数只负责释放本对象「拥有」且「动态分配」的资源。栈上数组(如 int buf[1024])、全局数组、静态数组、或由其他模块分配并移交所有权的内存,都不该在析构函数里用 delete[]。
- 对栈数组执行
delete[]是未定义行为,轻则崩溃,重则破坏栈帧 - 如果构造函数接收外部传入的指针(比如
Buffer(int* p)),需明确所有权约定:若不接管,析构函数就不该释放;若接管,必须文档化并确保调用方不再使用原指针 - 常见陷阱:误把
std::string::c_str()返回的指针当成本地分配内存去delete[]
释放前检查指针是否为空,但不必过度防御
delete[] 对空指针是安全的,C++ 标准保证其无操作(no-op)。所以无需写 if (data != nullptr) delete[] data;。
立即学习“C++免费学习笔记(深入)”;
- 冗余检查反而干扰阅读,还可能掩盖逻辑问题(比如多次释放后指针没置空)
- 真正该做的是:在
delete[]后立即将指针设为nullptr,避免悬挂指针被二次释放 - 更健壮的做法是用智能指针——
std::unique_ptr<int[]>在析构时自动调用delete[],且不可复制,天然防误用
多维数组的释放容易漏掉层级
用 new int*[rows] 配合循环 new int[cols] 分配的“伪二维数组”,必须按相反顺序释放:先逐行 delete[],再 delete[] 行指针数组。
int** mat = new int*[rows];
for (int i = 0; i < rows; ++i)
mat[i] = new int[cols];
<p>// 析构中:
for (int i = 0; i < rows; ++i)
delete[] mat[i]; // ✅ 先删每行
delete[] mat; // ✅ 再删行指针数组- 漏掉内层循环 → 内存泄漏
- 颠倒顺序(先
delete[] mat)→ 外层指针失效,内层无法访问,导致泄漏 - 这种手动管理极易出错,生产代码中应改用
std::vector<std::vector<int>>或一维展平 + 索引计算
实际项目里,99% 的数组管理需求都不需要手写 delete[]。真正难的不是语法,而是所有权边界是否清晰——一旦模糊,析构函数就变成定时炸弹。


















