Non-Constant Generator Single-Pass Initialization during Construction

131 views Asked by At

Is there a way to construct a new std::vector with uninitialized (non-zero) values or even prettier through a generator (similar to std::generate_n()) constructor argument that produces the desired non-standard (non-constant) values without first initializing all elements to zero? This because I want a (random) mockup-creation api to be as locality-efficient as possible, thereby only writing container elements once. Wouldn't it be neat to have a generator-constructor for the std::vector (and possibly others)?! Why hasn't C++ already added this to the Standard?

The following constructor-like C function illustrates the write-once-behaviour I seek for the custom-initialize construction of std::vector:

// Allocate-and-Generate a random int array of length \p n.
int * gen_rand(size_t n)
{
  int *v = malloc(n); // allocate only 
  for (size_t i=0; i<n; i++) {
    v[i] = rand(); // first write
  }
}

I believe it boils down to the behaviour of the STL Allocator used, since it is responsible for writing the initial zeros (or not).

If we use the std::vector constructor with iterators we first have to allocate and write the random values somewhere else, even worse than using push_back().

1

There are 1 answers

2
pmr On BEST ANSWER

You can precede the use of the generator with a call to vector::reserve. This will have exactly the same behavior as the C code you show. You will still need to use a back_insert_iterator as the size of the vector will still be zero.

#include <vector>
#include <cstdlib>
#include <algorithm>
#include <iterator>
#include <iostream>


int main()
{
  std::vector<int> v;
  v.reserve(10);
  std::generate_n(std::back_inserter(v), 10, []() { return rand(); });
  for(auto x : v)
    std::cout << x << std::endl;
  // unsafe version
  std::vector<int> v2;
  // 10 uninitialized integers
  v2.resize(10);
  // make sure never to write more than the exact amount, otherwise this will be UB
  std::generate_n(v.begin(), 10, []() { return rand(); });

  return 0;
}