问题
What are the advantages of using std::make_unique over the new operator for initializing a 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 new in 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_unique than to use new?
回答1:
Advantages
make_uniqueteaches users "never saynew/deleteandnew[]/delete[]" without disclaimers.make_uniqueshares two advantages withmake_shared(excluding the third advantage, increased efficiency). First,unique_ptr<LongTypeName> up(new LongTypeName(args))must mentionLongTypeNametwice, whileauto up = make_unique<LongTypeName>(args)mentions it once.make_uniqueprevents the unspecified-evaluation-order leak triggered by expressions likefoo(unique_ptr<X>(new X),unique_ptr<Y>(new Y)). (Following the advice "never saynew" is simpler than "never saynew, unless you immediately give it to a namedunique_ptr".)make_uniqueis carefully implemented for exception safety and is recommended over directly callingunique_ptrconstructors.
When not use make_unique
- Don't use
make_uniqueif you need a custom deleter or are adopting a raw pointer from elsewhere.
Sources
- Proposal of std::make_unique.
- Herb Sutter's GotW #89 Solution: Smart Pointers
回答2:
The difference is that std::make_unique returns an object of type std::unique_ptr and new returns a pointer to the created object. For memory allocation failures, they will both throw. Hold on, it's not that simple. Read further.
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 new expression succeeds but the second new expression throws?
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...
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_unique will constrain you towards exception safety. In this case, std::make_unique provides a "Basic Exception Safety" that the memory allocated and object created by new will never be orphaned no matter what. Even till the ends of time... :-)
You should read Herb Sutter GoTW102
来源:https://stackoverflow.com/questions/37514509/advantages-of-using-stdmake-unique-over-new-operator