The first case does not perform a double allocation, it performs two allocations, one for the managed object and one for the control block of the shared_ptr
.
For the second case, cppreference has a good explanation for why std::make_shared usually only performs one memory allocation it says (emphasis mine going forward):
This function typically allocates memory for the T object and for the
shared_ptr's control block with a single memory allocation (it is a
non-binding requirement in the Standard). In contrast, the declaration
std::shared_ptr p(new T(Args...)) performs at least two memory
allocations, which may incur unnecessary overhead.
and from std::shared_ptr section it says:
When shared_ptr is created by calling std::make_shared or
std::allocate_shared, the memory for both the control block and the
managed object is created with a single allocation. The managed object
is constructed in-place in a data member of the control block. When
shared_ptr is created via one of the shared_ptr constructors, the
managed object and the control block must be allocated separately. In
this case, the control block stores a pointer to the managed object.
This make_shared
description is consistent with the C++11 draft standard which says in section 20.7.2.2.6
shared_ptr creation
template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args);
template<class T, class A, class... Args>
shared_ptr<T> allocate_shared(const A& a, Args&&... args);
[...]
Remarks: Implementations should perform no more than one memory
allocation. [ Note: This provides efficiency equivalent to an
intrusive smart pointer. —end note ]
[ Note: These functions will typically allocate more memory than
sizeof(T) to allow for internal bookkeeping structures such as the
reference counts. —end note ]
Herb Sutter has a more detailed explanation of the advantages of using make_shared
in GotW #89 Solution: Smart Pointers and points out some advantages:
- It reduces allocation overhead
- It improves locality.
- Avoids an explicit new.
- Avoids an exception safety issue.
Be aware that when using std::weak_ptr using make_shared has some disadvantages.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…