5

这个问题是关于 new[] int 和 new [] int() 在语义和性能上的差异,以及在向 allocator_traits::construct() 添加 ctor 参数的完美转发时可能无意中创建的从第一个措辞到第二个措辞的变化。这个问题不涉及一个非常明显的问题,即默认 ctor 在由向量的 resize() 构造的所有新元素上运行。

对我来说,在调整大小时清除内置类型向量的元素似乎是一种浪费。但是 VS2012 的实现使得 resize(n) 以及因此带有 count 参数的构造函数实际上将分配的值数组设置为 0。

我还在标准中找到了对此的支持(http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2012/n3485.pdf),但我认为它可能是一个错误在那里,因为它依赖于最近涉及完美转发的条款:

第 507 页:

template <class T, class... Args>
static void construct(Alloc& a, T* p, Args&&... args);

5 效果:调用

::new (static_cast<void*>(p)) T(std::forward<Args>(args)...).

并且由于 new int() 必须根据同一文档第 191 页上的第 11 条将值设置为 0,因此向量中的浪费实现是正确的。

问题是标准提交是否真的希望构造调用的空参数包导致行为从默认构造更改为基本类型的值构造。

4

2 回答 2

6

不,这不是一个错误。

该标准的先前版本resize(n)创建了一个元素,然后将其复制到向量中的所有新位置。新的措辞是故意允许不可复制但只是可构造的类型。

于 2013-04-09T11:13:26.573 回答
5

容器从不保存未初始化的对象是一个不变量。这意味着任何增加容器大小的东西都必须以某种方式初始化所有新元素。这是一个特性,而不是缺陷——访问未初始化的值是未定义的行为,如果某些值未初始化,您将无法重新分配(或插入)。例如:

std::vector<int> v;
v.resize( 20 );
v.insert( v.begin(), 1 );

resize 如果没有初始化它创建的元素,最后一行将导致未定义的行为。

于 2013-04-09T11:13:51.343 回答