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
(以及 b
和 c
)?
我开始看草案 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()
,现在,根据 ,我认为 a
、b
和 c
将是 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
的调用仍然会表现相同。
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
的值,因为它们是内置类型。
#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
(以及 b
和 c
)?
我开始看草案 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 lastsize() - sz
elements from the sequence. Otherwise, appendssz - 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 withinX
.
现在,我需要知道里面发生了什么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 atp
usingargs
, withm == 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()
,现在,根据 ,我认为 a
、b
和 c
将是 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 byp
).
并且作为 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
的调用仍然会表现相同。
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
的值,因为它们是内置类型。