#include <vector>
struct S { int x; };
std::vector<S> v;
int main() { v.resize(1000); return v[42].x; }
Is the above program guaranteed to return 0 in C++14? Why?
Is the above program guaranteed to return 0 in C++14? Why?
Yes. From [vector.capacity]:
void resize(size_type sz);
13 Effects: Ifsz < size()
, erases the lastsize() - sz
elements from the sequence. Otherwise, appendssz - size()
default-inserted elements to the sequence.
Where, from [container.requirements.general]:
An element of
X
is default-inserted if it is initialized by evaluation of the expressionallocator_traits<A>::construct(m, p)
wherep
is the address of the uninitialized storage for the element allocated withinX
.
construct
for std::allocator<T>
does, from [default.allocator]:
template <class U, class... Args> void construct(U* p, Args&&... args);
Effects:
::new((void *)p) U(std::forward<Args>(args)...)
So, that's value-initialization. We're doing new S()
, not new S
, so the member x
will be zero-initialized.
The ways of avoiding this behavior (if desired) are either:
construct
: one empty (which would do default-initialization) and one taking Args&&...
. S
that does no initialization.Yes, because std::vector::resize
and similar methods perform value initialization by default† which in turn value-initializes the members of aggregates:
From cppr:
The effects of value initialization are:
[...]
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;
and the Zero Initialiation part does what we need:
If T is an non-union class type, all base classes and non-static data members are zero-initialized, and all padding is initialized to zero bits. The constructors, if any, are ignored.
And of course, zero initialization of our member does the right thing:
If T is a scalar type, the object's initial value is the integral constant zero explicitly converted to T.
†The default allocator does, custom allocators may use different initialization. You can use those to leave such values unitialized, see the full article on default-insert.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With