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.