C++ std::make_unique和std::unique_ptr与new的区别
C++ std::make_unique和std::unique_ptr与new的区别,c++,c++11,c++14,smart-pointers,unique-ptr,C++,C++11,C++14,Smart Pointers,Unique Ptr,std::make_unique是否有像std::make_shared这样的效率优势 与手动构造std::unique\u ptr相比: std::make_unique<int>(1); // vs std::unique_ptr<int>(new int(1)); std::使_唯一(1);//vs std::unique_ptr(新int(1)); std::make_unique和std::make_shared有两个原因: 这样就不必显式列出
std::make_unique
是否有像std::make_shared
这样的效率优势
与手动构造std::unique\u ptr
相比:
std::make_unique<int>(1); // vs
std::unique_ptr<int>(new int(1));
std::使_唯一(1);//vs
std::unique_ptr(新int(1));
std::make_unique
和std::make_shared
有两个原因:
这样就不必显式列出模板类型参数
使用std::unique\u ptr
或std::shared\u ptr
构造函数时的额外异常安全。(请参见注释部分。)
这与运行时效率无关。控制块和T
一次分配有点不对劲,但我认为这更多的是一种奖励,而不是这些功能存在的动机。使其独一无二的动机主要有两个方面:
make_unique
对于创建临时表是安全的,而明确使用new
时,您必须记住不使用未命名临时表的规则
foo(make_unique<T>(), make_unique<U>()); // exception safe
foo(unique_ptr<T>(new T()), unique_ptr<U>(new U())); // unsafe*
foo(make_unique(),make_unique());//例外安全
foo(unique_ptr(new T()),unique_ptr(new U());//不安全*
- 添加
make_unique
最后意味着我们可以告诉人们“永远不要”使用new
,而不是以前的规则“永远不要”使用new
,除非你制作了一个unique\ptr
”
还有第三个原因:
make_unique
不需要重复使用类型unique\u ptr(新T())
->make\u unique()
没有一个原因涉及到使用make_shared
提高运行时效率的方法(由于避免了第二次分配,以可能更高的峰值内存使用率为代价)
*预计C++17将包含一个规则更改,这意味着这不再是不安全的。请参阅C++委员会文件和 < P> >为什么使用<代码> STD::UNQuyjyPTR(new Ar))或<代码> STD::SyrdYpPTR(new A.)(<代码> >直接代替<代码> STD::MaMaj**())/Case>不能访问类< <代码> >当前代码之外的构造函数> < /P> < P>考虑函数调用< /P>
void function(std::unique_ptr<A>(new A()), std::unique_ptr<B>(new B())) { ... }
这里的要点是:代码> STD::MaMax独占< /COD>和 STD::MaMaIOLION/<代码>现在是临时对象,并且在C++标准中正确地指定临时对象的清理:它们的析构函数将被触发,内存被释放。因此,如果可以,请始终选择使用std::make_unique
和std::make_shared
分配对象make_shared
是否比编写冗长的代码更有效,因为make_shared
可以在单个分配中同时分配对象空间和控制块空间。这样做的代价是,对象不能与控制块分开释放,因此如果您大量使用weak_ptr
,那么最终可能会使用更多内存。也许这是一个很好的起点,请参阅此链接以获得详细解释:它们也是为了异常安全。@0x499602D2,这是一个很好的补充。对于未来的读者来说,C++17不允许函数参数的交错,因此异常安全的参数不再适用。两个并行std::make_-shared
的内存分配将确保在另一个内存分配发生之前,至少其中一个被包装在智能指针中,因此不会泄漏。更合理的说法是std::unique_-ptr
和std::shared_-ptr
是我们可以告诉人们这样做的原因“切勿使用new
。“@TimothyShields是的,我就是这个意思。只是在C++11中,我们有了make_shared
,因此make_unique
是以前缺失的最后一个部分。你可以简单地提到,或者链接到,不使用未命名临时变量的原因吗?实际上,从,我得到了它。。。从这个答案中,考虑以下函数调用<代码> f>代码>:<代码> f(UNQuijpPTR(new t),函数,即yAcNeNeWORKE());代码>-引用答案:编译器可以(按顺序)调用:newt
,可以抛出的函数()
,唯一的ptr(…)
。显然,如果你可以抛出的函数实际上抛出了,那么你就泄漏了<代码>使_唯一
防止出现这种情况。我曾经不得不使用std::unique_ptr(new T())的一个原因是T的构造函数是私有的。即使对std::make_unique的调用在类T的公共工厂方法中,它也不会编译,因为std::make_unique的一个底层方法无法访问私有构造函数。我不想成为那个方法的朋友,因为我不想依赖std::make_unique的实现。因此,唯一的解决方案是,在我的工厂中调用T类的new方法,然后将其封装在std::unique_ptr中。
void function(std::make_unique<A>(), std::make_unique<B>()) { ... }