Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does C++11 mandate that a vector<int> zeros the elements in resize()? [duplicate]

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.

like image 300
Bengt Gustafsson Avatar asked Apr 09 '13 11:04

Bengt Gustafsson


2 Answers

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.

like image 64
Bo Persson Avatar answered Sep 28 '22 04:09

Bo Persson


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.

like image 39
James Kanze Avatar answered Sep 28 '22 06:09

James Kanze