No good reason. This looks like a QoI issue in libstdc++.
Using clang 4.0, libc++ does not have this issue., while libstdc++ does.
The libstdc++ implementation with RTTI relies on get_deleter
:
void* __p = _M_refcount._M_get_deleter(typeid(__tag));
_M_ptr = static_cast<_Tp*>(__p);
__enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr);
_M_ptr = static_cast<_Tp*>(__p);
and in general, get_deleter
isn't possible to implement without RTTI.
It appears that it is using the deleters position and the tag to store the T
in this implementation.
Basically, the RTTI version used get_deleter
. get_deleter
relied on RTTI. Getting make_shared
to work without RTTI
required rewriting it, and they took an easy route that caused it to do two allocations.
make_shared
unifies the T
and reference counting blocks. I suppose with both variable sized deleters and variable sized T
things get nasty, so they reused the deleter's variable sized block to store the T
.
A modified (internal) get_deleter
that did not do RTTI and returned a void*
might be enough to do what they need from this deleter; but possibly not.
std::shared_ptr<foo>(new foo())
? No, just 2. Hmm. – Miasma