Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Advantages of using std::make_unique over new operator [duplicate]

People also ask

Why should I use Make_unique?

It is recommended to use the 'make_unique/make_shared' function to create smart pointers. The analyzer recommends that you create a smart pointer by calling the 'make_unique' / 'make_shared' function rather than by calling a constructor accepting a raw pointer to the resource as a parameter.

Does Make_unique throw?

A little late, but make_unique can itself throw according to cppreference: make_unique "may throw std::bad_alloc or any exception thrown by the constructor of T. If an exception is thrown, this function has no effect." So how is that exception safe?

What is std :: unique_ptr?

std::unique_ptr is a smart pointer that owns and manages another object through a pointer and disposes of that object when the unique_ptr goes out of scope. The object is disposed of, using the associated deleter when either of the following happens: the managing unique_ptr object is destroyed.

Can unique_ptr be null?

Nullability - a scoped_ptr or unique_ptr can be null, a value object can never be. Polymorphism - a value object is always exactly its static type, but you can substitute in different derived types for a unique_ptr. The previously-held object is automatically destroyed when you do this.


Advantages

  • make_unique teaches users "never say new/delete and new[]/delete[]" without disclaimers.

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

  • make_unique prevents 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_unique is carefully implemented for exception safety and is recommended over directly calling unique_ptr constructors.

When not to use make_unique

  • Don't use make_unique if you need a custom deleter or are adopting a raw pointer from elsewhere.

Sources

  1. Proposal of std::make_unique.
  2. Herb Sutter's GotW #89 Solution: Smart Pointers

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