Ad

How Does Use Of Make_unique Prevent Memory-leak, In C++?

fn(unique_ptr<A>{new A{}},unique_ptr<B>{new B{}});

is troublesome as A or B gets leaked if an exception is thrown there.

fn(make_unique<A>(),make_unique<B>());

on the other hand is considered exception-safe.

Question:

Why? How does use of make_unique prevent memory-leak?
What does make_unique do that the defaultunique_ptr does not?

Kindly help me out, please.
Thank you.

Ad

Answer

How does use of make_unique prevent memory-leak, in C++?

std::make_unique doesn't "prevent" memory-leak in the sense that it's still possible to write memory leaks in programs that use std::make_unique.

What does std::make_unique is make it easier to write programs that don't have memory leaks.


A or B gets leaked if an exception is thrown there.

Why?

Pre C++17:

Because if you allocate A, then call constructor of B before constructing the std::unique_ptr that was supposed to own A, and the constructor of B throws, then A will leak (or same happens with A and B reversed).

Since C++17:

There's no leak since the scenario described above cannot happen anymore in the shown example.

What does make_unique do that the default unique_ptr does not?

std::make_unique allocates memory, and either successfully returns a valid std::unique_ptr, or throws an exception without leaking memory.

std::unique_ptr(T*) accepts a pointer that was allocated separately. If an exception is thrown before the constructor is called, then there will never have been a unique pointer owning the allocation.


It's possible to fix the (pre-C++17) bug without using std::make_unique:

auto a = std::unique_ptr<A>{new A{}};
auto b = std::unique_ptr<B>{new B{}};
fn(std::move(a), std::move(b));

But if you always use std::make_unique, then you won't accidentally make the mistake of writing leaky version. Furthermore, std::make_unique lets you avoid writing new which allows you to use the rule of thumb "write exactly one delete for each new". 0 new -> 0 delete.

Ad
source: stackoverflow.com
Ad