Непрерывная однопроходная инициализация генератора во время строительства - PullRequest
0 голосов
/ 29 января 2012

Есть ли способ создать новые std::vector с неинициализированными (ненулевыми) значениями или даже более красивыми с помощью генератора (аналогично std::generate_n()) аргумент конструктора, который выдает желаемые нестандартные (непостоянные) значения без , сначала инициализирующих все элементы в ноль?Это потому, что я хочу, чтобы (случайный) API создания макета был как можно более эффективным с точки зрения локальности, тем самым записывая элементы контейнера только один раз.Разве не было бы здорово иметь генератор-конструктор для std::vector (и, возможно, других) ?!Почему C ++ еще не добавил это в стандарт?

Следующая, похожая на конструктор функция C иллюстрирует поведение однократной записи, которое я ищу для пользовательской инициализируемой конструкции 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
  }
}

Я полагаю, что все сводится к поведению используемого распределителя STL, поскольку он отвечает за запись начальных нулей (или нет).

Если мы используем конструктор std::vector с итераторами, мы сначаладолжны распределять и записывать случайные значения в другом месте, даже хуже, чем при использовании push_back().

1 Ответ

3 голосов
/ 30 января 2012

Вы можете использовать генератор до вызова vector::reserve. Это будет иметь точно такое же поведение, как и код C, который вы показываете Вам все равно нужно будет использовать back_insert_iterator, так как размер vector все равно будет равен нулю.

#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;
}
...