std :: make_unique和std :: unique_ptr之间的差异与new

时间:2014-03-21 23:20:29

标签: c++ c++11 c++14 smart-pointers unique-ptr

std::make_unique是否具有std::makes_shared等效率优势?

与手动构建std::unique_ptr

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

4 个答案:

答案 0 :(得分:119)

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*
    
  • 添加make_unique最终意味着我们可以告诉人们“从不”使用new而不是之前的规则“永远不会”使用new,除非您制作一个unique_ptr“。

还有第三个原因:

  • make_unique不需要冗余类型使用。 unique_ptr<T>(new T()) - &gt; make_unique<T>()

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

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

答案 1 :(得分:10)

std::make_uniquestd::make_shared有两个原因:

  1. 这样您就不必明确列出模板类型参数。
  2. 使用std::unique_ptrstd::shared_ptr构造函数的额外异常安全性。 (参见注释部分here。)
  3. 它并不是关于运行时效率的。有一点关于控制块和T一次性分配,但我认为这更多的是奖励而不是这些功能存在的动机。

答案 2 :(得分:5)

您必须直接使用std::unique_ptr(new A())std::shared_ptr(new A())而不是std::make_*()的原因是无法访问当前范围之外的类A的构造函数。< / p>

答案 3 :(得分:0)

考虑函数调用

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

假设新的A()成功,但是新的B()抛出异常:您捕获到该异常以恢复程序的正常执行。不幸的是,C ++标准不要求销毁对象A并释放其内存:内存静默泄漏,无法清除它。通过将A和B包装到std::make_uniques中,可以确保不会发生泄漏:

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

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