If you have a vector containing structs with uninitialized members, is this undefined behavior. The context for this is a vector which is created but then filled in a parallel context, Thus the default initialization of the vector is wasted.
Example
template< typename T >
struct uninitialized
{
T t;
uninitialized(){};
uninitialized & operator=( T const & inT ){ t = inT ; return *this; }
uninitialized & operator=( T && inT ){ t = std::move( inT ); return *this; }
};
std::vector< uninitialized< int > > example()
{
auto vector = std::vector< uninitialized< int > >(500);
// Other code unrelated to vector
for( auto & element : vector ) element = 0; // For loop as stand in for potentially parallel context
// "0" is simply used as a stand in to keep the example simple
// Code which might use vector
return vector;
}
Worth mentioning, the uninitialized members will never be read before they are eventually initialized.
If it matters for the anwser, the intended use is for simple numerical types such as int
or aggragate types consisting of those numeric types.
(Also to avoid unnecessary comments, reserve
+ push_back
is not relevant here as the final order of the vector is important)
There is no undefined-behavior (UB) in the posted code:
Creating a vector
with 500 elements is OK:
auto vector = std::vector<uninitialized<int>>(500);
All the elements will be constructed with uninitialized
's default constructor. The fact that it does not initialize T t
is immeterial here.
The loop with assigments is also OK:
for( auto & element : vector ) element = 0;
All the elements will be assigned via uninitialized::operator=(T const & inT )
and their T t
will be set to 0
.
You can only have UB if you attempt to read an initialized value, but you mentioned that you will not do that, so you should be OK.