make_unique 是 c++14 引入的安全创建 std::unique_ptr 的辅助函数,解决 new 表达式调用顺序不确定导致的资源泄漏问题,需包含 头文件,不支持自定义删除器和聚合初始化,参数完美转发给构造函数。

make_unique 是什么,为什么不能直接 new
make_unique 是 C++14 引入的辅助函数,用于安全、简洁地创建 std::unique_ptr。它不是语法糖,而是解决 new + 构造函数调用顺序不确定导致的资源泄漏风险——比如 func(new T(a), new T(b)) 中若 new T(b) 抛异常,new T(a) 就泄露了。
所以别写 std::unique_ptr<t>(new T(args...))</t>,既啰嗦又不安全。
- 必须包含头文件
<memory></memory> - 只支持 C++14 及以上;C++11 用户需自己实现或改用
make_shared(但注意:shared_ptr 语义不同) - 不接受自定义删除器(如带
FILE*的清理逻辑),此时得手写std::unique_ptr<t d>(ptr, deleter)</t>
基本用法和参数转发规则
make_unique 会完美转发参数给目标类型的构造函数,行为和 make_shared 类似,但返回的是 unique_ptr。
常见写法:
auto p = std::make_unique<:string>("hello");<br>auto arr = std::make_unique<int>(10); // 创建长度为 10 的 int 数组<br>auto p2 = std::make_unique<widget>(1, 'c', true); // 调用 Widget(int, char, bool)</widget></int></:string>
- 对于数组类型(
T[]),只能传一个 size 参数,不能初始化元素(C++14 不支持make_unique<t>{a,b,c}</t>) - 对非数组类型,参数列表完全匹配构造函数签名,不支持聚合初始化(如
struct S {int a; double b;};不能用make_unique<s>(1, 2.0)</s>,除非有对应构造函数) - 若类构造函数是 explicit,
make_unique仍可调用,无隐式转换干扰
常见错误:编译失败或行为异常
典型报错:error: no matching function for call to 'make_unique' 或 cannot convert from 'int' to 'std::unique_ptr<int>'</int>。
- 忘记加模板参数:写成
std::make_unique("abc")❌,必须写std::make_unique<:string>("abc")</:string>✅ - 误把数组长度当元素值:
std::make_unique<int>(5, 1)</int>❌(第二个参数非法),正确是std::make_unique<int>(5)</int>,然后手动赋值 - 试图用
make_unique构造 delete-incomplete 类型(如前向声明的类):编译可能通过,但在析构时崩溃 —— 因为unique_ptr需要完整类型才能生成正确的删除器 - 在模板中使用时,若类型依赖于模板参数,记得加
template关键字:std::make_unique<t>.template operator()(...)</t>(极少用,但真遇到会卡住)
和 make_shared 对比:什么时候该选哪个
两者都做“安全构造”,但语义和开销不同:make_unique 总是单分配(堆上只分配对象内存),make_shared 是双用途分配(对象 + 控制块合并在一次 malloc 中)。
- 需要独占所有权、且不共享控制块 → 用
make_unique - 确定后续可能升级为 shared_ptr(比如缓存、回调传递)→ 直接用
make_shared,避免二次分配 - 对象很大,但控制块很小 →
make_unique内存更紧凑;反之若频繁拷贝 shared_ptr,make_shared更省内存和 cache 行 - 没有默认构造函数的类,
make_unique支持任意构造参数,make_shared同样支持 —— 这点没区别
真正容易被忽略的是:哪怕你只想要 unique_ptr,如果类析构函数是 noexcept(false),而你又在多线程里大量创建/销毁,make_unique 的异常安全性仍是硬性保障 —— 它不依赖控制块布局,也不受引用计数干扰。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











