std::make_unique
是否像std::make_shared
一样有任何效率优势?
与手动构造std::unique_ptr
相比:
std::make_unique<int>(1); // vs
std::unique_ptr<int>(new int(1));
std::make_unique
是否像std::make_shared
一样有任何效率优势?
与手动构造std::unique_ptr
相比:
std::make_unique<int>(1); // vs
std::unique_ptr<int>(new int(1));
make_unique
的动机主要有两个方面:
make_unique
is safe for creating temporaries, whereas with explicit use of new
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' use new
rather than the previous rule to "'never' use new
except when you make a unique_ptr
".
还有第三个原因:
make_unique
不需要冗余类型使用。 unique_ptr<T>(new T())
-> make_unique<T>()
这些原因都不涉及像使用 make_shared
一样改善运行时效率(因为避免了第二次分配,但可能导致峰值内存使用量更高)。
* 预计 C++17 将包含规则更改,这意味着这种情况将不再是不安全的。请参阅 C++ 委员会文件P0400R0和P0145R3。
std::unique_ptr
和std::shared_ptr
是我们可以告诉人们“永远不要使用new”的原因。 - Timothy Shieldsmake_shared
,所以make_unique
是之前缺失的最后一块拼图。 - bames53f
: f(unique_ptr<T>(new T), function_that_can_throw());
- 引用答案:编译器可以按照顺序调用:new T
,function_that_can_throw()
,unique_ptr<T>(...)
。显然,如果 function_that_can_throw
真的抛出异常,那么会有内存泄漏。make_unique
可以防止这种情况发生。 因此,我的问题已得到解答。 - Dan Nissenbaumstd::make_unique
和 std::make_shared
的存在有两个原因:
std::unique_ptr
或 std::shared_ptr
构造函数,它们具有额外的异常安全性。(参见此处的注释部分。)这并不是关于运行时效率的。其中有关控制块和 T
一次性分配的内容,但我认为这更多是一个奖励而非这些函数存在的动机。
std::make_shared
的内存分配将确保在另一个内存分配发生之前至少有一个被包装在智能指针中,因此不会出现泄漏。 - MathBunny如果无法在当前作用域外访问类 A
的构造函数,则需要直接使用 std::unique_ptr(new A())
或 std::shared_ptr(new A())
,而不能使用 std::make_*()
。
考虑函数调用
void function(std::unique_ptr<A>(new A()), std::unique_ptr<B>(new B())) { ... }
new A()
成功,但new B()
抛出异常:您捕获它以恢复程序的正常执行。不幸的是,C++标准并不要求销毁对象A
并释放其内存:内存会默默泄漏,并且没有办法清理它。通过将A
和B
封装在std::make_unique()
调用中,您可以确保不会发生内存泄漏: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()
来分配对象。
make_shared
相较于手写长代码是否更加高效呢? - Ed Healmake_shared
可以在单个分配中同时分配对象和控制块的空间。代价是如果您经常使用weak_ptr
,那么对象无法单独释放,必须与控制块一起释放,这可能导致使用更多的内存。 - bames53