C++ std::make_unique 和 std::unique_ptr 与 new 的区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22571202/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:07:23  来源:igfitidea点击:

Differences between std::make_unique and std::unique_ptr with new

c++c++11c++14smart-pointersunique-ptr

提问by NFRCR

Does std::make_uniquehave any efficiency benefits like std::make_shared?

是否std::make_unique有任何效率优势std::make_shared

Compared to manually constructing std::unique_ptr:

与手动构建相比std::unique_ptr

std::make_unique<int>(1);         // vs
std::unique_ptr<int>(new int(1));

回答by bames53

The motivation behind make_uniqueis primarily two-fold:

背后的动机make_unique主要有两个方面:

  • make_uniqueis safe for creating temporaries, whereas with explicit use of newyou have to remember the rule about not using unnamed temporaries.

    foo(make_unique<T>(), make_unique<U>()); // exception safe
    
    foo(unique_ptr<T>(new T()), unique_ptr<U>(new U())); // unsafe*
    
  • The addition of make_uniquefinally means we can tell people to 'never' use newrather than the previous rule to "'never' use newexcept when you make a unique_ptr".

  • make_unique创建临时文件是安全的,而在显式使用时,new您必须记住不使用未命名临时文件的规则。

    foo(make_unique<T>(), make_unique<U>()); // exception safe
    
    foo(unique_ptr<T>(new T()), unique_ptr<U>(new U())); // unsafe*
    
  • 添加make_uniquefinally 意味着我们可以告诉人们“从不”使用,new而不是之前的规则“从不”使用,new除非您制作一个unique_ptr“。

There's also a third reason:

还有第三个原因:

  • make_uniquedoes not require redundant type usage. unique_ptr<T>(new T())-> make_unique<T>()
  • make_unique不需要冗余类型使用。unique_ptr<T>(new T())->make_unique<T>()

None of the reasons involve improving runtime efficiency the way using make_shareddoes (due to avoiding a second allocation, at the cost of potentially higher peak memory usage).

没有一个原因涉及像 usingmake_shared那样提高运行时效率(由于避免了第二次分配,代价是可能更高的峰值内存使用量)。

* It is expected that C++17 will include a rule change that means that this is no longer unsafe. See C++ committee papers P0400R0and P0145R3.

* 预计 C++17 将包含规则更改,这意味着这不再是不安全的。参见 C++ 委员会论文P0400R0P0145R3

回答by Timothy Shields

std::make_uniqueand std::make_sharedare there for two reasons:

std::make_uniquestd::make_shared在那里有两个原因:

  1. So that you don't have to explicitly list the template type arguments.
  2. Additional exception safety over using std::unique_ptror std::shared_ptrconstructors. (See the Notes section here.)
  1. 这样您就不必显式列出模板类型参数。
  2. 使用std::unique_ptrstd::shared_ptr构造函数的额外异常安全。(请参阅此处的注释部分。)

It's not really about runtime efficiency. There is the bit about the control block and the Tbeing allocated all at once, but I think that's more a bonus and less a motivation for these functions to exist.

这与运行时效率无关。有一点是关于控制块和同时T分配的,但我认为这更多是一种奖励,而不是这些功能存在的动机。

回答by Volodymyr Lashko

A reason why you would have to use std::unique_ptr(new A())or std::shared_ptr(new A())directly instead of std::make_*()is being unable to access the constructor of class Aoutside of current scope.

您必须使用std::unique_ptr(new A())orstd::shared_ptr(new A())直接代替的一个原因std::make_*()是无法访问A当前范围之外的类的构造函数。

回答by Dhanya Gopinath

Consider function call

考虑函数调用

void function(std::unique_ptr<A>(new A()), std::unique_ptr<B>(new B())) { ... }

Suppose that new A()succeeds, but new B()throws an exception: you catch it to resume the normal execution of your program. Unfortunately, the C++ standard does not require that object A gets destroyed and its memory deallocated: memory silently leaks and there's no way to clean it up. By wrapping A and B into std::make_uniquesyou are sure the leak will not occur:

假设 newA()成功,但 newB()抛出异常:您捕获它以恢复程序的正常执行。不幸的是,C++ 标准不要求对象 A 被销毁并释放其内存:内存会悄悄泄漏,并且无法清理它。通过将 A 和 B 包裹起来,std::make_uniques您可以确保不会发生泄漏:

void function(std::make_unique<A>(), std::make_unique<B>()) { ... }

The point here is that std::make_unique<A>and std::make_unique<B>are now temporary objects, and cleanup of temporary objects is correctly specified in the C++ standard: their destructors will be triggered and the memory freed. So if you can, always prefer to allocate objects using std::make_uniqueand std::make_shared.

这里的重点是std::make_unique<A>std::make_unique<B>现在是临时对象,并且在 C++ 标准中正确指定了临时对象的清理:它们的析构函数将被触发并释放内存。因此,如果可以,请始终使用std::make_uniqueand分配对象std::make_shared