#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;
}
What will be v[0].a
(and b
and c
)?
I am starting looking at the draft N4659 Working Draft, Standard for Programming
Language C++ searching for 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.
from there I need to know what default-inserted means and I arrive at:
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
.
Now, I need to know what happen inside construct
, I found this note
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 ]
Am I fine? Does my snippet use a specialized allocators? I think that at the end my snippet will call new T()
and now, according to https://stackoverflow.com/a/8280207 I think a
, b
and c
, will be 0
, am I correct?
The default behavior of
allocator_traits<A>::construct(m, p)
is defined in [allocator.traits.members]/5 it it states it does
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)...)
.
Since std::vector<T> v;
use the default allocator std::allocator
, and std::allocator
lacks a construct
member, you fall back to the placement new initialization and if you expand it out you'll have
::new (static_cast<void*>(p)) T();
and if we look up what T()
does we get from [dcl.init]/11 that
An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.
and [dcl.init]/8 states that value initialization will
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;
So all of the members of each newly created object will be zero initialized which means in this case they will all have the value of 0
since they are built in types.