std::make_unique补上了c++11中unique_ptr缺失的标准工厂函数,解决了异常不安全、类型重复和语义模糊三大缺陷;它不是语法糖,而是强制原子操作,确保分配与构造一体完成、异常安全且可优化。

std::make_unique 解决了 C++11 中 unique_ptr 的什么缺陷
它补上了 C++11 里唯一缺失的智能指针构造助手——std::shared_ptr 有 std::make_shared,std::weak_ptr 可由 std::shared_ptr 构造,唯独 std::unique_ptr 没有标准的工厂函数。C++11 只能写 std::unique_ptr<t>(new T(args))</t>,这带来三个实际问题:
- 异常不安全:参数求值顺序未定义,
new T(a)成功后、unique_ptr构造前若抛异常,内存就泄漏了 - 类型重复:
T在模板参数和new表达式里各写一次,易错且违背 DRY - 语义模糊:
new是底层操作符,混在业务逻辑里干扰资源管理意图
为什么 std::make_unique 是原子操作而不是语法糖
它不是简单封装 new + unique_ptr 构造,而是强制要求编译器在单次内存分配中完成对象构造,并把所有权立即绑定到返回的 std::unique_ptr。这意味着:
- 如果
T的构造函数抛异常,分配的内存会被自动释放,不会留下裸指针 - 多个
std::make_unique调用在函数参数中不会相互干扰——每个都独立完成“分配+构造+封装” - 编译器可对内部调用做优化(比如避免额外的移动),而手动写
new则无此保障
std::make_unique 不支持的场景必须绕开
它设计目标明确:只负责“标准 new + 默认 delete”的单对象或数组构造。以下情况它帮不上忙,硬用会编译失败或行为错误:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
-
std::make_unique不接受自定义删除器——必须手写std::unique_ptr<t d></t>构造 - 不能用于初始化列表(如
{1,2,3}),C++17 才通过std::make_unique_for_overwrite或直接构造支持 - 数组创建必须显式写
std::make_unique<t></t>,写成std::make_unique<t>(n)</t>是创建一个值为n的T,不是数组 - 不支持非类型模板参数或运行时类型擦除(比如
void*场景)
兼容性与编译器落地细节
虽然标准是 C++14,但实际支持早于标准发布:
- GCC 4.9+、Clang 3.4+、MSVC 2013 Update 2+ 都已完整支持,无需开启特殊 flag
- C++11 模式下部分编译器(如 GCC 4.8)提供扩展支持,但行为不保证一致,不应依赖
- 数组版本
std::make_unique<t></t>和完美转发参数在 C++14 中才完全稳定;C++11 仅支持无参或单参(某些实现扩展支持多参,但非标准)
真正容易被忽略的是:即使你写了 auto p = std::make_unique<myclass>(x, y)</myclass>,如果 MyClass 的构造函数是 explicit 且接受右值引用,而你传入左值,编译仍会失败——make_unique 完美转发,不改变值类别。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










