NFR*_*RCR 118 c++ smart-pointers unique-ptr c++11 c++14
是否std::make_unique
有像任何效率优势std::make_shared
?
与手动构建相比std::unique_ptr
:
std::make_unique<int>(1); // vs
std::unique_ptr<int>(new int(1));
Run Code Online (Sandbox Code Playgroud)
bam*_*s53 134
背后的动机make_unique
主要是双重的:
make_unique
创造临时工作是安全的,而明确使用new
你必须记住不使用未命名临时工的规则.
foo(make_unique<T>(), make_unique<U>()); // exception safe
foo(unique_ptr<T>(new T()), unique_ptr<U>(new U())); // unsafe*
Run Code Online (Sandbox Code Playgroud)添加make_unique
最终意味着我们可以告诉人们"从不"使用new
而不是先前的规则"永远不会"使用,new
除非你做了unique_ptr
".
还有第三个原因:
make_unique
不需要冗余类型使用.unique_ptr<T>(new T())
- >make_unique<T>()
没有任何原因涉及使用方式提高运行时效率make_shared
(由于避免了第二次分配,代价是可能更高的峰值内存使用).
*预计C++ 17将包含规则更改,这意味着这不再是不安全的.参见C++委员会论文P0400R0和P0145R3.
您必须使用std::unique_ptr(new A())
或std::shared_ptr(new A())
直接替代的std::make_*()
原因是无法访问A
当前范围之外的类的构造函数.
小智 6
考虑函数调用
void function(std::unique_ptr<A>(new A()), std::unique_ptr<B>(new B())) { ... }
Run Code Online (Sandbox Code Playgroud)
假设new A()
成功,但new B()
抛出异常:您捕获它以恢复程序的正常执行。不幸的是,C++ 标准不要求A
销毁对象并释放其内存:内存会悄悄泄漏,并且无法清理它。通过将A
和包装B
到std::make_unique()
调用中,您可以确定不会发生泄漏:
void function(std::make_unique<A>(), std::make_unique<B>()) { ... }
Run Code Online (Sandbox Code Playgroud)
这里的要点是std::make_unique<A>()
,并std::make_unique<B>()
返回临时对象,并且临时对象的清理在 C++ 标准中是正确指定的:它们的析构函数将被触发并释放内存。因此,如果可以的话,总是更喜欢使用std::make_unique()
和分配对象std::make_shared()
。