This question is about the difference in semantics and performance of new[] int and new [] int() and the change from the first to the second wording possibly unintendedly created when adding perfect forwarding of ctor arguments to allocator_traits::construct(). This question does NOT concern the quite obvious issue that a default ctor is run on all new elements constructed by resize() of a vector.
To me clearing the elements of a vector of built in types at resize seems like a waste. But VS2012 is implemented so that resize(n) and as a consequence also the constructor with a count parameter actually sets the allocated array of values to 0.
Also I found support for this in the standard, (http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2012/n3485.pdf) but I think it may be a mistake that it got there, as it relies on a recent clause involving perfect forwarding:
page 507:
template <class T, class... Args>
static void construct(Alloc& a, T* p, Args&&... args);
5 Effects: invokes
::new (static_cast<void*>(p)) T(std::forward<Args>(args)...).
and as new int() must set the value to 0 according to clause 11 on page 191 of the same document the wasteful implementation in vector is correct.
The question is whether the standard committe actually wanted the empty parameter pack of the construct call to cause a change in behaviour from default construction to value construction for basic types.
No, it's not a mistake.
The previous version of the standard had resize(n)
create one element and then copy that to all the new positions in the vector. The new wording is deliberate to allow for types that are not copyable, but just constructible.
It is an invariant that a container never holds an uninitialized object. This means that anything which increases the size of the container must initialize all of the new elements somehow. This is a feature, not a defect—accessing uninitialized values is undefined behavior, and you couldn't reallocate (or insert) if some of the values were not initialized. E.g.:
std::vector<int> v;
v.resize( 20 );
v.insert( v.begin(), 1 );
The last line would result in undefined behavior if the resize
hadn't initialized the elements it created.
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