You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++17中std::make_unique与直接构造std::unique_ptr的优劣对比

C++17中std::make_unique与直接构造std::unique_ptr的优劣对比

先明确一个核心前提:和std::make_shared与直接构造std::shared_ptr的差异不同,std::make_unique<T>()和std::unique_ptr<T>{new T}在内存分配次数上完全一致——都是只做一次内存分配,不存在性能上的本质差距。那既然C++17已经支持从初始化语句自动推导模板参数(比如可以直接写auto ptr = std::unique_ptr{new T};不用显式指定std::unique_ptr<T>),make_unique还有啥不可替代的价值?咱们来慢慢捋:

「std::make_unique」的优势

  • 异常安全是最大亮点:举个实际场景,假设你有个函数void func(std::unique_ptr<T>, int),如果直接写func(std::unique_ptr<T>{new T}, some_func_that_throws()),编译器可能会先执行new T,再调用some_func_that_throws()。要是这个函数抛出异常,那new出来的内存就没人接管了,直接造成内存泄漏。但用func(std::make_unique<T>(), some_func_that_throws())就不会有这问题——make_unique把内存分配和智能指针构造做成了原子操作,就算后面的函数抛异常,也不会有泄漏风险。
  • 代码更简洁清爽:虽然C++17能推导模板参数,但make_unique写起来还是更短!比如auto ptr = std::make_unique<MyClass>(arg1, arg2);对比auto ptr = std::unique_ptr<MyClass>{new MyClass(arg1, arg2)};,少敲不少重复代码,可读性也更好。
  • 彻底规避裸指针暴露:用make_unique的话,代码里完全看不到new关键字,符合现代C++“尽量避免裸指针和显式new/delete”的编码风格,也减少了不小心把裸指针传给其他函数的风险。
  • 数组构造更直观:创建数组类型的unique_ptr时,std::make_unique<T[]>(10)的写法比std::unique_ptr<T[]>{new T[10]}更符合函数式构造的逻辑,不容易搞错数组模板参数的写法。

「直接构造std::unique_ptr」的优势

  • 支持自定义删除器:make_unique不支持传递自定义删除器参数,如果你的场景需要给unique_ptr指定特殊的删除逻辑(比如释放特定资源、调用自定义销毁函数),那只能用直接构造的方式,比如std::unique_ptr<T, MyDeleter> ptr{new T, MyDeleter{}};。
  • 定制内存分配细节:要是你需要用重载的operator new、或者从特定内存池分配内存,这时候必须自己调用自定义分配逻辑拿到裸指针,再交给unique_ptr管理——make_unique无法满足这种个性化的分配需求。

总结

除非你需要自定义删除器或者特殊的内存分配逻辑,否则在C++17及以后,优先选择std::make_unique——它带来的异常安全、代码简洁性和风格一致性都是实打实的好处,绝不仅仅是旧版本里的模板参数推导功能而已。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 11:38:11