C++ 使用 std::make_unique 优于 new 运算符的优点

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37514509/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 14:41:51  来源:igfitidea点击:

Advantages of using std::make_unique over new operator

c++c++14unique-ptr

提问by niting

What are the advantages of using std::make_uniqueover the newoperator for initializing a std::unique_ptr?

什么是使用的优势,std::make_uniquenew运营商的初始化std::unique_ptr

In other words, why is

换句话说,为什么

std::unique_ptr<SomeObject> a = std::make_unique(SomeObject(...))

better than doing

比做更好

std::unique_ptr<SomeObject> a = new SomeObject(...)

I tried looking up a lot online and I do know that it is a good rule of thumb to avoid the operator newin modern C++, but I am not sure what the advantages are in this exact scenario. Does it prevent any kind of memory leaks that might happen? Is it faster to do a std::make_uniquethan to use new?

我尝试在网上查了很多资料,我知道new在现代 C++ 中避免使用运算符是一个很好的经验法则,但我不确定在这种情况下有什么优势。它是否可以防止可能发生的任何类型的内存泄漏?做 astd::make_unique比使用快new吗?

采纳答案by 101010

Advantages

好处

  • make_uniqueteaches users "never say new/deleteand new[]/delete[]" without disclaimers.

  • make_uniqueshares two advantages with make_shared(excluding the third advantage, increased efficiency). First, unique_ptr<LongTypeName> up(new LongTypeName(args))must mention LongTypeNametwice, while auto up = make_unique<LongTypeName>(args)mentions it once.

  • make_uniqueprevents the unspecified-evaluation-order leak triggered by expressions like foo(unique_ptr<X>(new X), unique_ptr<Y>(new Y)). (Following the advice "never say new" is simpler than "never say new, unless you immediately give it to a named unique_ptr".)

  • make_uniqueis carefully implemented for exception safety and is recommended over directly calling unique_ptrconstructors.

  • make_unique教导用户“永远不要说new/deletenew[]/ delete[]”没有免责声明。

  • make_unique共享两个优势make_shared(不包括第三个优势,提高效率)。首先,unique_ptr<LongTypeName> up(new LongTypeName(args))必须提LongTypeName两次,而提auto up = make_unique<LongTypeName>(args)一次。

  • make_unique防止由像表达式触发的未指定的评价顺序泄漏foo(unique_ptr<X>(new X)unique_ptr<Y>(new Y))。(遵循“永不说new”的建议比“永不说”更简单new,除非您立即将其提供给指定的人unique_ptr。)

  • make_unique为异常安全精心实现,建议直接调用unique_ptr构造函数。

When not to use make_unique

何时不使用 make_unique

  • Don't use make_uniqueif you need a custom deleter or are adopting a raw pointer from elsewhere.
  • make_unique如果您需要自定义删除器或从其他地方采用原始指针,请不要使用。

Sources

来源

  1. Proposal of std::make_unique.
  2. Herb Sutter's GotW #89 Solution: Smart Pointers
  1. 的提案std::make_unique
  2. Herb Sutter 的 GotW #89 解决方案:智能指针

回答by WhiZTiM

The difference is that std::make_uniquereturns an object of type std::unique_ptrand newreturns a pointer to the created object. For memory allocation failures, they will both throw. Hold on, it's not that simple. Read further.

区别在于std::make_unique返回一个类型的对象std::unique_ptrnew返回一个指向创建对象的指针。对于内存分配失败,它们都会抛出。等等,没那么简单。进一步阅读。

Consider such a function below:

考虑下面这样的函数:

void func(ClassA* a, ClassB* b){
     ......
}

When you make a call like func(new A(), new B()); The compiler may choose to evaluate the function arguments from left to right, or in any order it so wishes. Let's assume left to right evaluation: What happens when the first newexpression succeeds but the second newexpression throws?

当您拨打类似电话时func(new A(), new B());编译器可以选择从左到右计算函数参数,或者按照它希望的任何顺序。让我们假设从左到右计算:当第一个new表达式成功但第二个new表达式抛出时会发生什么?

The real danger here is when you catch such exception; Yes, you may have caught the exception thrown by new B(), and resume normal execution, but new A()already succeeded, and its memory will be silently leaked. Nobody to clean it up... * sobs...

这里真正的危险是当你捕捉到这样的异常时;是的,你可能已经捕获到 抛出的异常new B(),并恢复正常执行,但是new A()已经成功了,它的内存会被悄悄泄漏。没有人来清理它...... *抽泣......

But with make_unique, you cannot have a leak because, stack unwinding will happen ( and the destructor of the previously created object will run). Hence, having a preference for make_uniquewill constrain you towards exception safety. In this case, std::make_uniqueprovides a "Basic Exception Safety"that the memory allocated and object created by newwill never be orphaned no matter what. Even till the ends of time... :-)

但是使用make_unique,您不能有泄漏,因为将发生堆栈展开(并且先前创建的对象的析构函数将运行)。因此,偏好make_unique将限制您使用异常安全。在这种情况下,std::make_unique提供一个基本异常安全,分配的内存和创建的对象new无论如何都不会孤立。即使直到时间结束... :-)

You should read Herb Sutter GoTW102

你应该阅读Herb Sutter GoTW102