包含原始类型的struct容器,零初始化?

时间:2017-02-06 18:07:23

标签: c++ c++14

#include <vector>
struct S { int x; };
std::vector<S> v;
int main() { v.resize(1000); return v[42].x; }

上述程序是否保证在C ++ 14中返回0?为什么呢?

2 个答案:

答案 0 :(得分:3)

是的,因为<provider android:authorities="@string/content_authority" android:name=".package.ProviderClass" android:exported="false" android:syncable="true" /> 和类似方法默认执行值初始化,而这反过来初始化聚合成员:

来自cppr:

  

值初始化的影响是:
  [...]
  如果T是一个类型,其默认构造函数既不是用户提供也不是删除(也就是说,它可能是一个具有隐式定义或默认默认构造函数的类),该对象是零初始化的,然后它是默认的 - 如果它有一个非平凡的默认构造函数,则初始化;

并且Zero Initialiation部分可以满足我们的需求:

  

如果T是非联合类类型,则所有基类和非静态数据成员都是零初始化的,并且所有填充都初始化为零位。构造函数(如果有)将被忽略。

当然,我们会员的零初始化做了正确的事情:

  

如果T是标量类型,则对象的初始值是显式转换为T的整数常量零。

默认分配器可以,自定义分配器可以使用不同的初始化。您可以使用这些值将这些值保留为单位化,请参阅default-insert上的完整文章。

答案 1 :(得分:3)

  

上述程序是否保证在C ++ 14中返回0?为什么呢?

是。来自[vector.capacity]:

  

void resize(size_type sz);
   13效果:如果sz < size(),则删除序列中的最后size() - sz个元素。否则,请将sz - size() 默认插入的元素添加到序列中。

来自[container.requirements.general]:

  

X的元素是默认插入,如果它是通过评估表达式allocator_traits<A>::construct(m, p)初始化的,其中p是未初始化存储的地址在X内分配的元素。

construct的{​​p> std::allocator<T>来自[default.allocator]:

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

效果::new((void *)p) U(std::forward<Args>(args)...)

那么,这就是价值初始化。我们正在new S(),而不是new S,因此成员x将被初始化为零。

避免此行为的方式(如果需要)是:

  1. 更改分配器。提供自己的分配器类型,它具有construct的两个重载:一个为空(将进行默认初始化),另一个为Args&&...
  2. 更改类型。将默认构造函数添加到不进行初始化的S