Bar*_*rry 14 c++ vector allocator language-lawyer c++11
作为这个问题的后续,默认的allocator(std::allocator<T>)需要construct按如下方式实现(根据[default.allocator]):
Run Code Online (Sandbox Code Playgroud)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提供默认初始化的额外过载?就是这样的(借用凯西):
template <class U>
void construct(U* p) noexcept(std::is_nothrow_default_constructible<U>::value)
{
::new(static_cast<void*>(p)) U;
}
Run Code Online (Sandbox Code Playgroud)
是否有理由在呼叫案例中更喜欢值初始化?对我来说这似乎令人惊讶,这打破了通常的C++规则,我们只支付我们想要使用的内容.
†我认为这样的改变是不可能的,因为目前std::vector<int> v(100)会给你100 0秒,但我想知道为什么会这样......因为人们可以很容易地std::vector<int> v2(100, 0)以同样的方式要求有差异之间new int[100]和new int[100]{}.
在 C++03 中,分配器construct成员有两个参数:指针和值,用于执行复制初始化:
\n\n20.1.6 表 34
\n\n
a.construct(p,t)效果:
\n
\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0::new((void*)p) T(t)
construct采用两个参数可以追溯到 1994 年(第 18 页)。正如您所看到的,在最初的 Stepanov 概念中,它不是分配器接口的一部分(它不应该是可配置的),而是作为新放置的包装器存在。
唯一确定的方法是问 Stepanov 本人,但我认为原因如下:如果你想构造一些东西,你想用特定的值初始化它。如果您希望整数未初始化,则可以省略construct调用,因为 POD 类型不需要它。之后construct,其他相关函数被捆绑到分配器中,并且容器在它们上进行了参数化,从而为最终用户带来了一些初始化控制的损失。
因此,缺乏默认初始化似乎是出于历史原因:当 C++ 标准化并且标准的更高版本不会引入重大更改时,没有人考虑过它的重要性。
\n| 归档时间: |
|
| 查看次数: |
537 次 |
| 最近记录: |