应该allocator construct()默认初始化而不是值初始化? [英] Should allocator construct() default initialize instead of value initializing?

查看:215
本文介绍了应该allocator construct()默认初始化而不是值初始化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为此问题的后续工作,默认分配器( std :: allocator< T> ; )需要实现构造,如下所示(根据[default.allocator]):


  template< class U,class ... Args> 
void construct(U * p,Args& ... args);
:: new((void *)p)U(std :: forward& Args(args)...)




<也就是说,总是值初始化。其结果是 std :: vector< POD> v(num),对任何pod类型,将值初始化 num 元素 - 这比默认初始化 num 元素。



为什么没有 std :: allocator 提供默认初始化额外的过载?也就是说,像(借用 Casey ):

  template< class U> 
void construct(U * p)noexcept(std :: is_nothrow_default_constructible< U> :: value)
{
:: new(static_cast< void *>(p)
}

有没有理由更喜欢在呼叫中初始化值?这似乎令我惊讶的是,这打破了通常的C ++规则,我们只为我们想要使用的付出。






我认为这样的改变是不可能的, code> std :: vector< int> v(100)会给你100 0 s,但我想知道为什么是这样的情况...很容易需要 std :: vector< int>在 new int [100] new int [100]之间存在差异的相同方式, 100] {}

解决方案

在C ++ 03中,分配器用于执行复制初始化的指针和值:


20.1.6表34



a.construct(p,t)



效果:

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


code> construct 采取两个参数可以追溯到1994年(第18页)。正如你所看到的,在Stepanov概念中,它不是分配器接口的一部分(它不应该是可配置的),并且作为包装器存在于placement new。



只有方法知道肯定会问斯蒂芬诺本人,但我想这是因为如下:如果你想构造一些东西,你想用特定的值初始化它。如果你想要你的整数未初始化,你可以省略构造调用,因为它不需要POD类型。后来构造和其他相关的功能被捆绑到分配器和容器中参数化导致最终用户初始化的一些失去控制。



因此,似乎没有默认初始化是因为历史原因:没有人知道它的重要性,当C ++标准化,以后的版本的标准不会引入破裂的变化。 / p>

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

解决方案

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.

这篇关于应该allocator construct()默认初始化而不是值初始化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆