unique_ptr管理动态数组必须使用T[]特化版本,否则析构调用delete而非delete[]导致未定义行为;需显式声明std::unique_ptr<int[]>,构造推荐make_unique<N>(),不支持initializer_list初始化。

unique_ptr 管理动态数组必须用特化版本
直接用 std::unique_ptr<t></t> 指向 new T[n] 是未定义行为,析构时调用的是 delete 而非 delete[],导致内存泄漏或崩溃。C++ 标准为此提供了数组特化:必须显式使用 std::unique_ptr<t></t>。
-
std::unique_ptr<int></int>→ 对应new int,不能用于数组 -
std::unique_ptr<int></int>→ 对应new int[10],析构自动调用delete[] - 类型中的
[]不是可选语法糖,是模板参数的一部分,缺了就错
构造和访问数组元素的写法差异
数组版 unique_ptr 的构造方式和下标访问与普通指针一致,但不支持 get() 返回的裸指针直接当普通数组用(容易误删),且不能调用 release() 后手动 delete[]——除非你真清楚自己在做什么。
- 正确构造:
auto arr = std::make_unique<int>(100);</int>(推荐)或std::unique_ptr<int> ptr(new int[100]);</int> - 访问元素:
arr[5] = 42;✅;*arr是首元素,arr.get()返回int*,但别拿它去delete - 禁止操作:
arr.reset(new int(5));—— 类型不匹配,编译失败
为什么不用 make_unique 传初始化列表?
std::make_unique<t></t> 只接受一个 size 参数,不支持类似 {1,2,3} 的初始化列表。这是语言限制:数组长度必须在编译期或运行期明确为单一整数,无法从 initializer_list 推导大小。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 合法:
auto a = std::make_unique<int>(3); a[0]=1; a[1]=2; a[2]=3;</int> - 非法:
std::make_unique<int>({1,2,3});</int>—— 编译错误,无匹配重载 - 替代方案:若需初始化值,改用
std::vector;或用原始 new + 自定义 deleter(极少见)
自定义 deleter 不是常规解法,慎用
有人想绕过 T[] 特化,用 unique_ptr<t></t> 配合自定义 deleter 调用 delete[]。语法上可行,但破坏类型安全、增加认知负担,且无法使用 [] 下标运算符(operator[] 只对 T[] 特化定义)。
立即学习“C++免费学习笔记(深入)”;
- 反模式示例:
std::unique_ptr<int void> p(new int[10], [](int* p){ delete[] p; });</int> - 后果:不能写
p[3],必须用p.get()[3],且极易忘记自定义逻辑,协作时难维护 - 结论:除非对接 C API 强制要求裸指针+自定义释放,否则坚持用
unique_ptr<t></t>
最常被忽略的一点:模板参数里的 [] 必须紧贴类型名,写成 unique_ptr<int></int>(带空格)虽部分编译器容忍,但不符合标准,跨平台时可能失败。

















