Why is it better to use std::make_* instead of the constructor?

蹲街弑〆低调 提交于 2019-12-06 17:00:42

问题


There are some functions in the STL which start with the make_ prefix like std::make_pair, std::make_shared, std::make_unique etc. Why is it a better practice to use them instead of simply using the constructor ?

auto pair2 = std::pair< int, double >( 1, 2.0 );
auto pair3 = std::make_pair( 1, 2.0 );

std::shared_ptr< int > pointer1 = std::shared_ptr< int >( new int( 10 ) );
std::shared_ptr< int > pointer2 = std::make_shared< int >( 10 );
  • I just see that these functions make the code a little shorter, but is that all ?
  • Are there any other advantages ?
  • Are these functions safer to use ?

回答1:


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.




回答2:


Although it may be subjective, one main touted benefit for this technique is:

write code against interfaces, not implementations

In essence, function template instantiation performs type deduction based on the arguments you pass, whereas class template instantiation does not. As a consequence, you wouldn't have to pass template arguments as you would when instantiating the class directly.

It should be noted though, that this is not about "saving a few characters", but rather about making your code more general, and avoiding being tied to a concrete type in your function call.

However, this is not always the case, as your std::make_shared example showed, there are still cases in which you have to pass the type as a template argument. But, as Herb Sutter points out, there are several other advantages when it comes to using std::make_shared:

  1. You should write for clarity and correctness first, and std::make_shared achieves both of those (subjective, but I agree)

  2. using std::make_shared is more efficient, because it allocates your object as well as the shared_ptr object in one go, allowing for lower allocation overhead and a likely better cache alignment.




回答3:


make_unique hides from you "raw" pointer, what's usually a good thing - it's less error prone. make_shared may improve memory allocation for shared_ptr<X> instances. Normally when you use shared_ptr<X> constructor it will allocate memory twice, first for instance of X and second for it's internal data (e.g. reference counter). make_shared enables optimization - it will create single, internal structure comprising both X and reference counter, hence it will perform single memory allocation. And same as before it hides raw pointers.



来源:https://stackoverflow.com/questions/31232146/why-is-it-better-to-use-stdmake-instead-of-the-constructor

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!