본문으로 건너뛰기 C++ Generate Algorithms: std::fill, std::generate,

C++ Generate Algorithms: std::fill, std::generate,

C++ Generate Algorithms: std::fill, std::generate,

이 글의 핵심

std::fill writes a single value, std::generate calls a function for each element, and std::iota writes a sequential series. This guide covers all three with working examples including proper C++11 random number generation.

Overview

The C++ standard library has three algorithms for filling ranges with values:

AlgorithmHeaderWritesUse when
std::fill<algorithm>Same value to allResetting to zero, marking flags
std::fill_n<algorithm>Same value to first NPartial initialization
std::generate<algorithm>Callable result per elementComputed or random values
std::generate_n<algorithm>Callable for N elementsAppending generated data
std::iota<numeric>Sequential incrementsIndex sequences, ranges

std::fill

Writes the same value to every element in a range:

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

int main() {
    // Fill entire vector
    std::vector<int> v(8);
    std::fill(v.begin(), v.end(), 42);
    // v: {42, 42, 42, 42, 42, 42, 42, 42}

    // Fill part of a vector
    std::fill(v.begin() + 2, v.begin() + 5, 99);
    // v: {42, 42, 99, 99, 99, 42, 42, 42}

    // Works on any container
    std::array<bool, 10> flags;
    std::fill(flags.begin(), flags.end(), false);

    // Works on C arrays too
    int arr[5];
    std::fill(arr, arr + 5, -1);
    // arr: {-1, -1, -1, -1, -1}
}

std::fill_n

Fill exactly N elements starting at a position:

std::vector<int> v(10, 0);

// Set first 5 elements to 1
std::fill_n(v.begin(), 5, 1);
// v: {1, 1, 1, 1, 1, 0, 0, 0, 0, 0}

// Append N elements to a vector (with back_inserter)
std::vector<int> result;
std::fill_n(std::back_inserter(result), 4, 7);
// result: {7, 7, 7, 7}

std::generate

Calls a callable for each element and writes the result. The callable takes no arguments and returns a value:

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

int main() {
    std::vector<int> v(5);

    // Incrementing counter via stateful lambda
    int counter = 0;
    std::generate(v.begin(), v.end(), [&counter] {
        return counter++;
    });
    // v: {0, 1, 2, 3, 4}

    // Alternating values
    bool toggle = false;
    std::generate(v.begin(), v.end(), [&toggle] {
        toggle = !toggle;
        return toggle ? 1 : 0;
    });
    // v: {1, 0, 1, 0, 1}

    // Fibonacci sequence
    int a = 0, b = 1;
    std::generate(v.begin(), v.end(), [&a, &b] {
        int current = a;
        int next = a + b;
        a = b;
        b = next;
        return current;
    });
    // v: {0, 1, 1, 2, 3}
}

std::generate_n

Generate N elements and append to a container:

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

int main() {
    std::vector<int> v;

    // Append 5 squares
    int n = 0;
    std::generate_n(std::back_inserter(v), 5, [&n] {
        return n * n++;  // 0, 1, 4, 9, 16
    });
    // v: {0, 1, 4, 9, 16}
}

std::iota

Fills a range with consecutively incremented values. Defined in <numeric>:

#include <numeric>
#include <vector>
#include <list>
#include <iostream>

int main() {
    // Fill with 0, 1, 2, 3, 4
    std::vector<int> v(5);
    std::iota(v.begin(), v.end(), 0);
    // v: {0, 1, 2, 3, 4}

    // Start from a different value
    std::vector<int> w(5);
    std::iota(w.begin(), w.end(), 10);
    // w: {10, 11, 12, 13, 14}

    // Works with any incrementable type — including chars
    std::vector<char> letters(5);
    std::iota(letters.begin(), letters.end(), 'a');
    // letters: {'a', 'b', 'c', 'd', 'e'}

    // Build an index array for indirect sorting
    std::vector<int> indices(10);
    std::iota(indices.begin(), indices.end(), 0);
    // indices: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    // then sort indices by comparing data[i]
}

Indirect Sorting with iota

A common pattern: sort an index array instead of the data, to get sorted order without moving elements:

#include <numeric>
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>

int main() {
    std::vector<std::string> names = {"Charlie", "Alice", "Bob", "Dave"};

    // Build indices 0..n-1
    std::vector<int> indices(names.size());
    std::iota(indices.begin(), indices.end(), 0);

    // Sort indices by name value
    std::sort(indices.begin(), indices.end(),
        [&names](int a, int b) { return names[a] < names[b]; });

    // Print in sorted order without moving the original vector
    for (int i : indices) {
        std::cout << names[i] << '\n';  // Alice, Bob, Charlie, Dave
    }
}

Random Number Generation with generate

Use C++11 <random> instead of rand():

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

int main() {
    // Set up random engine and distribution
    std::mt19937 engine(std::random_device{}());  // Mersenne Twister, seeded
    std::uniform_int_distribution<int> dist(1, 100);  // integers in [1, 100]

    // Fill vector with random values
    std::vector<int> v(10);
    std::generate(v.begin(), v.end(), [&engine, &dist] {
        return dist(engine);
    });

    for (int x : v) std::cout << x << ' ';

    // Different distribution: normal (bell curve)
    std::normal_distribution<double> normal(0.0, 1.0);  // mean=0, stddev=1
    std::vector<double> samples(1000);
    std::generate(samples.begin(), samples.end(), [&engine, &normal] {
        return normal(engine);
    });
}

Why not rand()?

  • Poor statistical quality (short period, bad distribution)
  • Shared global state — not thread-safe
  • No control over distribution
  • <random> gives you proper distributions and thread-local engines

Functor-Based Generator

When a lambda captures too many variables, a functor class is cleaner:

#include <algorithm>
#include <vector>

class IdGenerator {
    int next_id_;
    int step_;
public:
    IdGenerator(int start = 1000, int step = 10)
        : next_id_(start), step_(step) {}

    int operator()() {
        int id = next_id_;
        next_id_ += step_;
        return id;
    }
};

int main() {
    std::vector<int> ids(5);
    std::generate(ids.begin(), ids.end(), IdGenerator(1000, 10));
    // ids: {1000, 1010, 1020, 1030, 1040}
}

Common Pitfalls

Empty container — nothing happens:

std::vector<int> v;  // size 0
std::fill(v.begin(), v.end(), 42);  // no-op — empty range
// Fix: resize first
v.resize(5);
std::fill(v.begin(), v.end(), 42);  // now works
// Or use fill_n with back_inserter:
std::fill_n(std::back_inserter(v), 5, 42);

Wrong capture in generate — lambda doesn’t update outer state:

int counter = 0;

// Wrong: [=] captures by value — counter inside lambda doesn't update outer counter
std::generate(v.begin(), v.end(), [=] { return counter++; });
// All elements get 0 — counter is a local copy in each call

// Correct: [&] captures by reference
std::generate(v.begin(), v.end(), [&] { return counter++; });
// Elements get 0, 1, 2, 3, 4 ...

fill is faster than generate for constants:

// Slow: lambda call overhead per element
std::generate(v.begin(), v.end(), [] { return 42; });

// Fast: optimized to memset-like operation for trivial types
std::fill(v.begin(), v.end(), 42);

Key Takeaways

  • std::fill — same value everywhere; often optimizes to memset for trivial types
  • std::fill_n — same value for first N elements; works with back_inserter to append
  • std::generate — calls a callable per element; use [&] capture for stateful generators
  • std::iota — sequential values with ++; in <numeric>, not <algorithm>
  • Use <random> with std::mt19937 and appropriate distributions — never rand()
  • Resize or use back_inserter before fill/generate — they don’t add elements, only write to existing positions

자주 묻는 질문 (FAQ)

Q. 이 내용을 실무에서 언제 쓰나요?

A. Fill C++ containers with std::fill, std::generate, and std::iota. Covers fill_n, generate_n, random number generation wi… 실무에서는 위 본문의 예제와 선택 가이드를 참고해 적용하면 됩니다.

Q. 선행으로 읽으면 좋은 글은?

A. 각 글 하단의 이전 글 또는 관련 글 링크를 따라가면 순서대로 배울 수 있습니다. C++ 시리즈 목차에서 전체 흐름을 확인할 수 있습니다.

Q. 더 깊이 공부하려면?

A. cppreference와 해당 라이브러리 공식 문서를 참고하세요. 글 말미의 참고 자료 링크도 활용하면 좋습니다.


같이 보면 좋은 글 (내부 링크)

이 주제와 연결되는 다른 글입니다.


이 글에서 다루는 키워드 (관련 검색어)

C++, Algorithm, generate, fill, STL 등으로 검색하시면 이 글이 도움이 됩니다.