std::make_unique不能创建带长度的动态数组,因其数组特化版本仅支持零参数;正确方式是用std::unique_ptr显式构造或更推荐使用std::vector。

std::make_unique 不能直接创建带长度的动态数组
它不支持像 std::make_unique<int>(10)</int> 这样传入长度参数——编译会报错:no matching function for call to 'make_unique'。这是因为 std::make_unique 对数组特化版本(T[])只接受零参数,即只构造默认初始化的数组,不支持运行时指定大小。
正确创建堆上动态数组的两种方式
如果目标是获得一个拥有所有权、自动管理生命周期的动态数组,必须绕过 std::make_unique 的限制:
- 用
std::unique_ptr<t></t>显式构造:std::unique_ptr<int> arr(new int[10]{})</int>—— 注意{}可触发值初始化(全零),否则是未定义值 - 用
std::vector替代(更推荐):std::vector<int> arr(10)</int>—— 自动管理、可变长、异常安全,且无原始指针语义负担
为什么 std::make_unique(n) 不行,但 std::make_unique(n) 可以?
这是模板偏特化导致的行为差异:
-
std::make_unique<int>(n)</int>调用的是非数组版本,n作为构造参数传给int的构造函数(即初始化为值n) -
std::make_unique<int>(n)</int>试图匹配数组特化版,但标准只定义了make_unique<t>(args...)</t>且要求args...为空;传入n就找不到匹配重载 - 这种设计是为了避免混淆:数组长度是分配语义,不是元素构造语义
真要用 unique_ptr 管理 C 风格数组,别忘加自定义删除器(仅限非内置类型)
对非 POD 类型(比如含析构函数的类),new T[n] 必须配 delete[],而默认的 unique_ptr<t></t> 删除器恰好就是 delete[],所以通常不用改。但如果你误写成 unique_ptr<t></t>(单对象版本)并指向数组,就会 UB —— 常见错误是:
std::unique_ptr<myclass> p(new MyClass[5]); // 错!用 delete 而非 delete[]</myclass>
务必确保类型后缀与分配方式一致:MyClass[] 对应 new MyClass[n],且不要试图用 make_unique 绕开这个约束。
std::make_unique 承担动态数组尺寸传递职责,这不是遗漏,而是有意为之的设计取舍。真正需要运行时长度 + RAII 的场景,std::vector 是唯一简洁可靠的解法。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











