Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Differences between std::make_unique and std::unique_ptr with new

People also ask

Does Make_unique call new?

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).

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.

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.

In what situation is a shared_ptr more appropriate than a unique_ptr?

Use unique_ptr when you want a single pointer to an object that will be reclaimed when that single pointer is destroyed. Use shared_ptr when you want multiple pointers to the same resource.


The motivation behind make_unique is primarily two-fold:

  • 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".

There's also a third reason:

  • make_unique does not require redundant type usage. unique_ptr<T>(new T()) -> make_unique<T>()

None of the reasons involve improving runtime efficiency the way using make_shared does (due to avoiding a second allocation, at the cost of potentially higher peak memory usage).

* It is expected that C++17 will include a rule change that means that this is no longer unsafe. See C++ committee papers P0400R0 and P0145R3.


std::make_unique and std::make_shared are there for two reasons:

  1. So that you don't have to explicitly list the template type arguments.
  2. Additional exception safety over using std::unique_ptr or std::shared_ptr constructors. (See the Notes section here.)

It's not really about runtime efficiency. There is the bit about the control block and the T being allocated all at once, but I think that's more a bonus and less a motivation for these functions to exist.


A reason why you would have to use std::unique_ptr(new A()) or std::shared_ptr(new A()) directly instead of std::make_*() is being unable to access the constructor of class A outside of current scope.


Consider function call

void function(std::unique_ptr<A>(new A()), std::unique_ptr<B>(new B())) { ... }

Suppose that new A() succeeds, but new B() throws an exception: you catch it to resume the normal execution of your program. Unfortunately, the C++ standard does not require that object A gets destroyed and its memory deallocated: memory silently leaks and there's no way to clean it up. By wrapping A and B into std::make_uniques you are sure the leak will not occur:

void function(std::make_unique<A>(), std::make_unique<B>()) { ... }

The point here is that std::make_unique<A> and std::make_unique<B> are now temporary objects, and cleanup of temporary objects is correctly specified in the C++ standard: their destructors will be triggered and the memory freed. So if you can, always prefer to allocate objects using std::make_unique and std::make_shared.