new[]分配的二维数组必须用delete[]逐层释放,否则触发未定义行为;正确做法是先循环delete[]每行,再delete[]指针数组;推荐用std::vector替代裸指针以确保异常安全和自动清理。

new[] 分配的二维数组必须用 delete[] 逐层释放
直接用 delete 释放 new[] 分配的内存会触发未定义行为,尤其对二维数组这种嵌套结构,漏掉任何一层都会导致内存泄漏或崩溃。
典型错误写法:delete ptr; 或只释放第一层指针数组、忘了释放每行数据。
- 如果用
int** arr = new int*[rows];配合循环arr[i] = new int[cols];,必须先遍历释放每行:delete[] arr[i];,再释放指针数组:delete[] arr; - 顺序不能颠倒——先删
arr,后续arr[i]就成了悬空指针,释放会崩 - 对应分配和释放必须严格匹配:
new[]↔delete[],new↔delete
用 vector> 替代裸指针更安全
手动管理二维动态内存极易出错,尤其是异常路径下容易遗漏释放。现代 C++ 推荐用 std::vector 自动管理。
-
std::vector<:vector>> mat(rows, std::vector<int>(cols));</int></:vector>—— 构造即初始化,析构自动清理全部内存 - 访问方式不变:
mat[i][j],支持push_back动态扩容 - 若需连续内存(如传给 C 接口),改用一维
std::vector<int></int>模拟二维:vec[i * cols + j],再用vec.data()获取原始指针
malloc/free 方式释放要注意类型擦除
用 malloc 分配二维数组(如 int**)时,free 不关心类型,但释放逻辑仍要分层,且不能混用 new/free 或 malloc/delete。
- 常见模式:先
int** arr = (int**)malloc(rows * sizeof(int*));,再循环arr[i] = (int*)malloc(cols * sizeof(int)); - 释放必须反向:循环
free(arr[i]);,再free(arr); - 错误示例:
delete[] arr;或delete arr[0];—— 类型不匹配,UB
RAII 封装能彻底规避释放问题
自己写类封装二维数组,把分配逻辑放进构造函数,释放放进析构函数,是根治手动释放疏漏的办法。
- 关键点:析构函数里必须检查指针是否为
nullptr,避免重复释放;拷贝构造/赋值需深拷贝或禁用(加= delete) - 示例成员变量:
int** data_ = nullptr;、size_t rows_ = 0;、size_t cols_ = 0; - 哪怕只用一次,也建议优先选
std::vector;只有在性能敏感且明确需要裸指针时,才考虑 RAII 封装
真正容易被忽略的是异常安全——分配中途抛异常时,已分配的内存必须被正确回收。裸指针做不到这点,而 vector 和 RAII 类天然支持。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











