std::vector of struct:调整向量大小后,struct 成员的初始值是多少?

std::vector of struct: what will be the initial values of the members of the struct after a vector resize?

#include <vector>
#include <iostream>

typedef struct {
   unsigned short a;
   unsigned short b;
   unsigned long  c;
}T;

int main(int,char**)
{
    std::vector<T> v;
    v.resize(256);
    std::cout << "a=" << v[0].a << " b=" << v[0].b << " c=" << v[0].c << "\n";
    return 0;
}

什么是 v[0].a(以及 bc)?

我开始看草案 N4659 Working Draft, Standard for Programming 语言 C++ 搜索 vector::resize:

26.3.11.3 vector capacity [vector.capacity] (at clause 13)

void resize(size_type sz);

Effects: If sz < size(), erases the last size() - sz elements from the sequence. Otherwise, appends sz - size() default-inserted elements to the sequence.

从那里我需要知道 default-inserted 是什么意思然后我得出:

26.2.1 General container requirements [container.requirements.general] (at clause 15.2)

— An element of X is default-inserted if it is initialized by evaluation of the expression

allocator_traits<A>::construct(m, p)

where p is the address of the uninitialized storage for the element allocated within X.

现在,我需要知道里面发生了什么construct,我找到了这张便条

26.2.1 General container requirements [container.requirements.general] (at the end of clause 15)

[ Note: A container calls allocator_traits<A>::construct(m, p, args) to construct an element at p using args, with m == get_allocator(). The default construct in allocator will call ::new((void*)p) T(args), but specialized allocators may choose a different definition. — end note ]

我还好吗?我的代码段是否使用 专用分配器 ?我认为最后我的代码片段会调用 new T(),现在,根据 ,我认为 abc 将是 0,我说得对吗?

是的,你是对的。您没有使用专门的(定制的)分配器。最后元素得到 value initialized. From DefaultInsertable:

By default, this will call placement-new, as by ::new((void*)p) T() (that is, value-initialize the object pointed to by p).

并且作为 value initialization 的结果,T 的所有成员都将被零初始化。

(强调我的)

if T is a class type with a default constructor that is neither user-provided nor deleted (that is, it may be a class with an implicitly-defined or defaulted default constructor), the object is zero-initialized and then it is default-initialized if it has a non-trivial default constructor;

Am I fine?

是的。

Does my snippet use a specialized allocators?

没有。您使用默认分配器 std::allocator

I think that at the end my snippet will call new T() and now, according to I think a, b and c, will be 0, am I correct?

正确。

Am I fine? Does my snippet use a specialized allocators?

是的,不,分配器不是专用的。 std::vector<T> 使用的默认分配器是 std::allocator<T>。目前 std::allocator<T>still specified to have a construct member 做同样的事情。但这是一个已弃用的成员。无论如何,即使它在未来被完全删除,通过 std::allocator_traits 的调用仍然会表现相同。

[allocator.traits.members]

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

Effects: Calls a.construct(p, std​::​forward<Args>(args)...) if that call is well-formed; otherwise, invokes ​::​new(static_­cast<void*>(p)) T(std​::​forward<Args>(args)...).

至于 new T() 所做的,你是 100% 正确的。

的默认行为
allocator_traits<A>::construct(m, p)

[allocator.traits.members]/5中定义,它声明它

Effects: Calls a.construct(p, std::forward<Args>(args)...) if that call is well-formed; otherwise, invokes ::new (static_­cast<void*>(p)) T(std::forward<Args>(args)...).

由于 std::vector<T> v; 使用默认分配器 std::allocator,并且 std::allocator 缺少 construct 成员,您返回到放置新初始化,如果您将其展开你会有

::new (static_­cast<void*>(p)) T();

如果我们查找 T() 我们从 [dcl.init]/11 得到什么

An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.

[dcl.init]/8声明值初始化将

if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;

因此每个新创建的对象的所有成员都将初始化为零,这意味着在这种情况下它们都将具有 0 的值,因为它们是内置类型。