最直接有效的办法是根本不用 new[],改用 std::vector 自动管理内存;必须返回指针时用 std::unique_ptr 包装,确保 delete[] 正确调用;避免 std::shared_ptr 管理数组,优先通过命名、注释和类型系统明确所有权。

用 std::vector 替代裸 new[]
最直接有效的办法是根本不用 new[]。C++ 标准库的 std::vector 自动管理内存,构造时分配、析构时释放,不会因调用方疏忽导致泄漏。
常见错误是函数返回 int* 并要求调用者 delete[],但没人能保证调用方记得或知道该怎么做。
- 把
int* arr = new int[n];换成std::vector<int> arr(n);</int> - 函数返回类型从
int*改为std::vector<int></int>(值返回安全,C++11 后有移动语义,无额外拷贝开销) - 如果必须返回指针(如兼容 C 接口),至少改用
std::unique_ptr<int></int>,见下一条
必须返回裸指针时,用 std::unique_ptr<int></int> 包装
当函数接口已被外部依赖(比如老项目或 C 风格 API),不能改返回值类型,又想避免手动 delete[],可用智能指针包装后转交所有权。
std::unique_ptr<int></int> 明确表示“我拥有这块数组”,且析构时自动调用 delete[],比 std::unique_ptr<int></int> 多一个 [] 很关键——漏掉它会导致未定义行为。
- 正确写法:
return std::unique_ptr<int>(new int[n]);</int> - 错误写法:
std::unique_ptr<int>(new int[n])</int>—— 会调用delete而非delete[],踩坑高发点 - 调用方接收后可直接用
ptr.get()获取原始指针(如传给 C 函数),但所有权仍在unique_ptr中,离开作用域即释放
别用 std::shared_ptr 管理数组,除非真需要共享所有权
std::shared_ptr 默认用 delete 释放,不支持 delete[],直接传 new int[n] 会崩溃或静默损坏内存。
虽然可以传自定义删除器:std::shared_ptr<int>(new int[n], [](int* p) { delete[] p; })</int>,但这增加了认知负担和出错概率。
- 多数场景下,数组生命周期由单一方控制,
std::unique_ptr更轻量、更清晰 - 若真需多处持有且共同决定释放时机,优先考虑重构:用
std::vector+ 引用/迭代器,而非裸数组指针 - 自定义删除器容易写错(比如忘记
[]或捕获错误),且无法被静态检查工具识别
函数文档和命名必须暴露内存责任
即使用了智能指针,如果函数名含 create、alloc、new,或注释没写清“caller owns”,调用方仍可能误判。
命名和注释不是锦上添花,而是防止误用的第一道防线。
- 函数名建议带语义:如
make_data_buffer()比getData()更暗示所有权转移 - 注释必须明确写出:
@return unique_ptr owning the array或@warning caller must delete[] the returned pointer - 如果接口允许,加编译期约束:返回
std::unique_ptr的函数,调用方不显式 move 就编译失败,天然防误用
真正难的不是写对那几行 delete[],而是在多人协作、跨模块调用、多年维护中,让“谁该释放”这件事永远无需猜测。类型系统比注释可靠,自动管理比人工约定牢靠——把责任推给编译器,比指望人不犯错要实在得多。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











