Should allocator construct() default initialize instead of value initializing?

不问归期 提交于 2019-12-21 03:46:37

问题


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'tstd::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]{}.


回答1:


In C++03 Allocators construct member took two arguments: pointer and value which was used to perform copy-initialization:

20.1.6 Table 34

a.construct(p,t)

Effect:
    ::new((void*)p) T(t)

construct taking two parameters can be traced back to 1994 (pg. 18). As you can see, in orignal Stepanov concepts it wasn't part of allocator interface (it wasn't supposed to be configurable) and was present just as wrapper over placement new.

Only way to know for sure would to ask Stepanov himself, but I suppose that reason was following: if you want to construct something, you want to initialize it with specific value. And if you want your integers uninitializated, you can just omit construct call since it is not needed for POD types. Later construct and other related function were bundled into allocators and containers were parametrized on them introducing some loss of control on initialization for end user.

So it seems that lack of default initialization is for historical reasons: nobody though about its importance when C++ was standardized and later versions of the Standard would not introduce breaking change.



来源:https://stackoverflow.com/questions/35902965/should-allocator-construct-default-initialize-instead-of-value-initializing

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