The function std::make_shared<T>()
is most often preferred to std::shared_ptr<T> {new T}
, because it will only make one allocation, as opposed to two allocations in the second example. There are a few other differences, as detailed in cppreference on std::make_shared.
To my knowledge, the case is different for std::make_unique<T>()
vs. std::unique_ptr<T> {new T}
. Before C++17, we needed the make_
functions to deduce template arguments, but since C++17, the compiler can derive them from the initialization statement.
Hence my question: what are the advantages and disadvantages of either approach of constructing a unique_ptr
? Is there a specific case for which make_unique
offers an advantage (other than template parameter deduction in earlier C++ editions)?
The advantages are:
std::make_unique<T>(/* initialiser args */)
:
T
once.make_shared
as well.new
keyword.std::unique_ptr<T>{ ::new T/* initialiser */ }
:
make_unique_for_overwrite
.T
with auto
in C++23:std::unique_ptr<T>{ ::new auto(function_returning_a_T()) }
.
T
's constructor args are by-value, this can also skip some moves:
struct X { X(std::mutex); }; // std::mutex used as example for immovable type
// auto x = std::make_unique<X>(std::mutex()); // Doesn't work
auto x = std::unique_ptr<X>{ ::new X(std::mutex()) }; // Works