본문 바로가기
개발/C++ (98,03,11,14,17,20,23)

Modern C++ : std::transform & std::accumulate (98)

by snowoods 2025. 9. 10.

Modern C++

std::transform & std::accumulate

 

개요

std::transformstd::accumulate는 C++ 표준 라이브러리의 <algorithm><numeric> 헤더에 포함된 강력한 함수입니다. std::transform은 범위 내의 각 원소에 지정된 연산을 적용하고 그 결과를 다른 범위에 저장하는 데 사용됩니다. std::accumulate는 범위 내의 모든 원소를 합산하여 단일 값을 계산하는 데 사용됩니다. 이 함수들은 반복문을 직접 작성하는 것보다 코드를 더 간결하고 가독성 높게 만들어 줍니다.

 

C++ 버전별 주요 키워드 도입 시기

  • C++98: std::transform, std::accumulate가 도입되었습니다.

 

내용 설명

std::transform

std::transform 함수는 두 가지 형태로 오버로드되어 있습니다.

  1. 단항 연산 (Unary Operation):
    • first1, last1: 입력 범위의 시작과 끝 반복자입니다.
    • d_first: 출력 범위의 시작 반복자입니다.
    • unary_op: 각 원소에 적용할 단항 연산자 (함수, 람다 등)입니다.
    • 입력 범위의 각 원소에 unary_op를 적용한 결과를 출력 범위에 저장합니다. 입력 범위와 출력 범위가 동일할 수도 있습니다.
  2. template<class InputIt, class OutputIt, class UnaryOperation> OutputIt transform(InputIt first1, InputIt last1, OutputIt d_first, UnaryOperation unary_op);
  3. 이항 연산 (Binary Operation):
    • 두 개의 입력 범위([first1, last1)[first2, ...) )를 받아서 각 위치의 원소 쌍에 binary_op를 적용합니다.
  4. template<class InputIt1, class InputIt2, class OutputIt, class BinaryOperation> OutputIt transform(InputIt1 first1, InputIt1 last1, InputIt2 first2, OutputIt d_first, BinaryOperation binary_op);

std::accumulate

std::accumulate 함수는 주어진 범위의 원소들을 합산합니다.

template<class InputIt, class T>
T accumulate(InputIt first, InputIt last, T init);
  • first, last: 합산할 범위의 시작과 끝 반복자입니다.
  • init: 초기값입니다. 합산 결과의 타입은 이 초기값의 타입에 따라 결정됩니다.

 

예제 코드

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

namespace
{
constexpr auto NUM_ELEMENTS = size_t{3U};
}; // namespace

std::int32_t gen()
{
    static auto seed = std::random_device{};
    static auto g = std::mt19937{seed()};
    static auto d = std::uniform_int_distribution<std::int32_t>{-10, 10};

    return d(g);
}

template <typename T>
void print_vector(const std::vector<T> &vec)
{
    for (const auto v : vec)
    {
        std::cout << v << '\n';
    }
    std::cout << '\n';
}

int main()
{
    auto my_vector = std::vector<std::int32_t>(NUM_ELEMENTS, 0U);
    std::generate(my_vector.begin(), my_vector.end(), gen);
    print_vector(my_vector);

    // 각 원소를 2배로 변환
    std::transform(my_vector.begin(),
                   my_vector.end(),
                   my_vector.begin(),
                   [](const auto val) { return val * 2; });
    print_vector(my_vector);

    // 각 원소를 다시 2로 나눔 (원상 복구)
    std::transform(my_vector.begin(),
                   my_vector.end(),
                   my_vector.begin(),
                   [](const auto val) { return val / 2; });
    print_vector(my_vector);

    // 모든 원소의 합계를 계산
    const auto sum1 = std::accumulate(my_vector.begin(), my_vector.end(), 0);
    std::cout << sum1 << '\n';

    return 0;
}

 

실행 결과

-3
5
-10

-6
10
-20

-3
5
-10

-8

참고: std::generate로 생성되는 값은 실행할 때마다 달라지므로 결과는 위와 다를 수 있습니다.

활용팁

  • std::transform: 벡터의 모든 원소에 특정 연산을 일괄 적용하거나(예: 모든 숫자를 제곱), 두 벡터의 각 원소를 더해 새로운 벡터를 만드는 등 데이터 변환 작업에 매우 유용합니다.
  • std::accumulate: 단순히 합계를 구하는 것 외에도, 세 번째 인자로 초기값을, 네 번째 인자로 이항 연산자를 전달하여 곱셈(초기값 1, std::multiplies<>()), 문자열 연결 등 다양한 집계 연산을 수행할 수 있습니다.