Aside from the benefit of enabling argument deduction (as already mentioned in other answers), there are also some other benefits.
std::make_pair<T1, T2>
takes care to not simply return std::pair<T1, T2>
. If you pass in a value using std::ref
, then the returned pair won't store a std::reference_wrapper
, it will store a reference.
std::make_shared
can combine allocations. shared_ptr
needs some place to hold things like the refcount, weak pointer list, etc. that cannot be stored in the shared_ptr
directly. These can be combined with the object being created, in one slightly larger block rather than in two separate blocks.
std::make_shared
and std::make_unique
both make sure that no object gets left behind if exceptions are thrown. If you call a function as f(std::shared_ptr<int>(new int), std::shared_ptr<int>(new int))
, then it's possible the compiler first allocates two int
objects, and then constructs two shared_ptr<int>
objects. If the second allocation fails, and no shared_ptr<int>
object is set up yet to release the memory on destruction, then you have a memory leak. std::make_shared
and std::make_unique
combine the allocation of int
and the construction of std::shared_ptr<int>
in a function call, and the other allocation of int
and the other construction of std::shared_ptr<int>
in another function call. Function calls cannot overlap, so if the second allocation fails, there is already a shared pointer that will be destroyed, undoing the first allocation as well.