std::make_unique 和 std::unique_ptr 内部有 new 的区别

Posted

技术标签:

【中文标题】std::make_unique 和 std::unique_ptr 内部有 new 的区别【英文标题】:Differences between std::make_unique and std::unique_ptr with new internally 【发布时间】:2019-04-04 07:00:25 【问题描述】:

这个问题是this question 的后续问题。

The accepted answer 状态:

make_unique 可以安全地创建临时对象,而明确使用 new 您必须记住不使用未命名临时对象的规则

我大致了解这是什么意思,并且我理解给出的示例,但是这在内部究竟是如何工作的?这些函数具体是做什么的,区别在哪里?

【问题讨论】:

阅读herbsutter.com/gotw/_102 【参考方案1】:

这些函数究竟做了什么,区别在哪里?

其实没什么神奇的。他们只是从这里转换用户代码:

f( std::unique_ptr<T1> new T1 , std::unique_ptr<T2> new T2  );

进入这个:

f( make_unique<T1>(), make_unique<T2>() );

只是为了避免编译器对以下操作进行排序的情况,因为它可能会在 C++14(包含)之前这样做:

new T1 new T2 先构建unique_ptr 构建第二个unique_ptr

如果第二步 (new T2) 抛出异常,则第一个分配的对象尚未被保护到 unique_ptr 中并泄漏。

make_unique 函数实际上写起来很简单,在 C++11 中一直被忽略。它在 C++14 中很容易引入。在这期间,每个人都会编写自己的make_unique 模板,或者在 Google 上搜索 Stephen T. Lavavej 编写的模板。

正如 StoryTeller 评论的那样,从 C++17 开始,这种交错不再被允许。

【讨论】:

自 C++17 以来,这种交错是不合法的。在符合 C++17 的编译器上不会以这种方式发生泄漏(尽管我仍然发现重复类型名称本身不好)。 @StoryTeller:我没查过,但是C++17中有unique_ptr的推导指南吗? 没有,甚至编译器生成的也被设计禁用。主要是因为推导指南无法区分是否应该仅根据构造函数的参数来推导T*T[]

以上是关于std::make_unique 和 std::unique_ptr 内部有 new 的区别的主要内容,如果未能解决你的问题,请参考以下文章

std::make_unique SFINAE 友好吗?

c_cpp 的std :: make_unique

通过 make_unique/make_shared 调用 initializer_list 构造函数

第23课 优先选用make系列函数

指向 std::unique_ptr 的内容

将 std::unique_ptr 类成员标记为 const