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
Differences between std::make_unique and std::unique_ptr with new
提问by NFRCR
Does std::make_unique
have 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_unique
is primarily two-fold:
背后的动机make_unique
主要有两个方面:
make_unique
is safe for creating temporaries, whereas with explicit use ofnew
you 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_unique
finally means we can tell people to 'never' usenew
rather than the previous rule to "'never' usenew
except when you make aunique_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_unique
finally 意味着我们可以告诉人们“从不”使用,new
而不是之前的规则“从不”使用,new
除非您制作一个unique_ptr
“。
There's also a third reason:
还有第三个原因:
make_unique
does 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_shared
does (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++ 委员会论文P0400R0和P0145R3。
回答by Timothy Shields
std::make_unique
and std::make_shared
are there for two reasons:
std::make_unique
并std::make_shared
在那里有两个原因:
- So that you don't have to explicitly list the template type arguments.
- Additional exception safety over using
std::unique_ptr
orstd::shared_ptr
constructors. (See the Notes section here.)
- 这样您就不必显式列出模板类型参数。
- 使用
std::unique_ptr
或std::shared_ptr
构造函数的额外异常安全。(请参阅此处的注释部分。)
It's not really about runtime efficiency. There is the bit about the control block and the T
being 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 A
outside 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_uniques
you 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_unique
and std::make_shared
.
这里的重点是std::make_unique<A>
和std::make_unique<B>
现在是临时对象,并且在 C++ 标准中正确指定了临时对象的清理:它们的析构函数将被触发并释放内存。因此,如果可以,请始终使用std::make_unique
and分配对象std::make_shared
。