As a followup to this question, the default allocator (std::allocator<T>
) is required to implement construct
as follows (according to [default.allocator]):
template <class U, class... Args> void construct(U* p, Args&&... args);
Effects:
::new((void *)p) U(std::forward<Args>(args)...)
That is, always value-initialization. The result of this is that std::vector<POD> v(num)
, for any pod type, will value-initialize num
elements - which is more expensive than default-initializing num
elements.
Why didn't† std::allocator
provide a default-initializing additional overload? That is, something like (borrowed from Casey):
template <class U>
void construct(U* p) noexcept(std::is_nothrow_default_constructible<U>::value)
{
::new(static_cast<void*>(p)) U;
}
Was there a reason to prefer value initialization in call cases? It seems surprising to me that this breaks the usual C++ rules where we only pay for what we want to use.
†I assume such a change is impossible going forward, given that currently std::vector<int> v(100)
will give you 100 0
s, but I'm wondering why that is the case... given that one could just as easily have required std::vector<int> v2(100, 0)
in the same way that there are differences between new int[100]
and new int[100]{}
.