std::make_unique
是否具有std::makes_shared
等效率优势?
与手动构建std::unique_ptr
:
std::make_unique<int>(1); // vs
std::unique_ptr<int>(new int(1));
答案 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
的方式提高运行时效率(由于避免了第二次分配,代价是可能更高的峰值内存使用量)。
答案 1 :(得分:10)
std::make_unique
和std::make_shared
有两个原因:
std::unique_ptr
或std::shared_ptr
构造函数的额外异常安全性。 (参见注释部分here。)它并不是关于运行时效率的。有一点关于控制块和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_unique
和std::make_shared
分配对象。