C++

Generate в C++: как заполнить vector и массив

В C++ std::generate — это алгоритм из заголовка <algorithm>. Он проходит по диапазону и записывает в каждый элемент значение, которое возвращает функция-генератор

Короткая схема:

std::generate(begin, end, generator);

Где generator — функция, lambda или объект, который можно вызвать без аргументов

Заполнить vector числами

Пример: заполнить std::vector числами от 1 до 5

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> numbers(5);
    int value = 1;

    std::generate(numbers.begin(), numbers.end(), [&value]() {
        return value++;
    });

    for (int number : numbers) {
        std::cout << number << " ";
    }

    return 0;
}

Вывод:

1 2 3 4 5

Вектор заранее создан размером 5. std::generate не добавляет новые элементы, а заполняет уже существующие

Заполнить массив

std::generate работает и с обычным массивом:

#include <algorithm>
#include <iostream>
#include <iterator>

int main() {
    int numbers[5];
    int value = 10;

    std::generate(std::begin(numbers), std::end(numbers), [&value]() {
        value += 10;
        return value;
    });

    for (int number : numbers) {
        std::cout << number << " ";
    }

    return 0;
}

Результат:

20 30 40 50 60

Заполнить случайными числами

Для случайных чисел лучше использовать <random>, а не старый rand()

#include <algorithm>
#include <iostream>
#include <random>
#include <vector>

int main() {
    std::vector<int> numbers(10);

    std::mt19937 engine(std::random_device{}());
    std::uniform_int_distribution<int> dist(1, 100);

    std::generate(numbers.begin(), numbers.end(), [&]() {
        return dist(engine);
    });

    for (int number : numbers) {
        std::cout << number << " ";
    }

    return 0;
}

Каждый запуск может дать новый набор чисел

generate и back_inserter

Важный момент: обычный std::generate заполняет существующий диапазон. Если вектор пустой, такой код ничего не сделает:

std::vector<int> numbers;
std::generate(numbers.begin(), numbers.end(), generator);

Если нужно именно добавить элементы, используйте std::generate_n с std::back_inserter:

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

int main() {
    std::vector<int> numbers;
    int value = 1;

    std::generate_n(std::back_inserter(numbers), 5, [&value]() {
        return value++;
    });

    for (int number : numbers) {
        std::cout << number << " ";
    }

    return 0;
}

Когда использовать std::generate

std::generate удобен, когда значение каждого элемента получается по правилу:

  • счетчик;
  • случайное число;
  • результат функции;
  • объект с изменяющимся состоянием;
  • тестовые данные для массива или вектора.

Если нужно просто заполнить все элементы одним значением, берите std::fill

generate и fill: в чем разница

std::fill записывает одно и то же значение во все элементы:

std::fill(numbers.begin(), numbers.end(), 10);

std::generate каждый раз вызывает генератор:

std::generate(numbers.begin(), numbers.end(), [&value]() {
    return value++;
});

Поэтому fill подходит для одинаковых значений, а generate — для последовательностей, случайных чисел и тестовых данных, где каждый элемент должен вычисляться отдельно

generate не меняет размер контейнера

Если вектор создан так:

std::vector<int> numbers(5);

в нем уже есть пять элементов, и generate их заполнит. Если вектор пустой:

std::vector<int> numbers;

диапазон begin() — end() пустой. Поэтому для добавления новых элементов нужен generate_n и back_inserter

Частые ошибки

Запускать generate по пустому vector

Если begin() == end(), диапазон пустой и алгоритм ничего не заполнит. Создайте размер заранее или используйте generate_n

Думать, что generator принимает индекс

Генератор для std::generate вызывается без аргументов. Если нужен индекс, храните счетчик во внешней переменной

Забыть include

Для std::generate нужен:

#include <algorithm>

Короткий вывод

std::generate в C++ заполняет существующий диапазон значениями из генератора. Для vector заранее задайте размер или используйте std::generate_n с std::back_inserter, если элементы нужно добавлять

Связанные материалы:

Что почитать дальше по C++

Если нужен общий маршрут по теме, откройте рубрику C++. Для соседних задач пригодятся эти разборы:

Подписаться
Уведомить о
guest
0 комментариев
Старые
Новые Популярные

Настройки cookie

0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x