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 0s, 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]{}.