본문 바로가기
-----ETC-----/C++ 고급 프로그래밍과 응용 프로젝트 시리즈

[C++ 고급 프로그래밍과 응용 프로젝트] Day 1: 람다 함수와 함수 객체

by cogito21_cpp 2024. 8. 1.
반응형

람다 함수 (Lambda Functions)

람다 함수는 인라인으로 정의된 익명 함수로, 함수 객체를 간편하게 정의할 수 있는 방법입니다. 람다 함수는 특히 코드에서 일회성으로 사용되는 짧은 함수를 정의할 때 유용합니다.

 

람다 함수의 기본 구조

람다 함수의 기본 구조는 다음과 같습니다:

[capture](parameters) -> return_type {
    // 함수 본문
};
  • capture: 람다 함수가 외부 범위에서 변수를 캡처하는 방식입니다.
  • parameters: 함수의 매개변수입니다.
  • return_type: 함수의 반환 타입입니다.
  • 함수 본문: 람다 함수의 실제 코드입니다.

기본 예제

람다 함수를 사용하여 벡터의 요소를 출력하는 예제를 살펴보겠습니다.

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

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 람다 함수 사용
    std::for_each(vec.begin(), vec.end(), [](int x) {
        std::cout << x << " ";
    });
    std::cout << std::endl;

    return 0;
}

 

이 예제에서 std::for_each 알고리즘을 사용하여 벡터 vec의 각 요소를 출력하는 람다 함수를 정의하고 사용합니다. 람다 함수는 [ ] 안에 캡처 목록을 작성하고, (int x)를 통해 매개변수를 정의하며, { std::cout << x << " "; } 부분에서 함수 본문을 작성합니다.


캡처 목록 (Capture List)

람다 함수는 외부 범위에 있는 변수를 캡처하여 사용할 수 있습니다. 캡처 목록에는 다음과 같은 옵션이 있습니다:

  • [ ] : 외부 변수를 캡처하지 않음
  • [=] : 외부 변수를 값으로 캡처
  • [&] : 외부 변수를 참조로 캡처
  • [x] : 변수 x를 값으로 캡처
  • [&x] : 변수 x를 참조로 캡처
  • [=, &x] : 모든 변수를 값으로 캡처하고, x는 참조로 캡처
  • [&, x] : 모든 변수를 참조로 캡처하고, x는 값으로 캡처

 

캡처 목록 사용 예제

다음 예제에서는 변수 ab를 값으로 캡처하고 참조로 캡처하는 두 가지 람다 함수를 보여줍니다.

#include <iostream>

int main() {
    int a = 10;
    int b = 20;

    // 값으로 캡처
    auto sum = [a, b]() {
        return a + b;
    };

    std::cout << "Sum: " << sum() << std::endl;

    // 참조로 캡처
    auto increment = [&a, &b]() {
        a++;
        b++;
    };

    increment();
    std::cout << "Incremented a: " << a << ", b: " << b << std::endl;

    return 0;
}

이 예제에서 sum 람다 함수는 ab를 값으로 캡처하여 a + b를 반환합니다. increment 람다 함수는 ab를 참조로 캡처하여 두 변수를 증가시킵니다.


함수 객체 (Function Objects)

함수 객체는 함수처럼 동작하는 객체로, operator()를 오버로딩하여 함수 호출 연산자를 정의합니다. 함수 객체는 상태를 가질 수 있으며, 함수 호출 간에 데이터를 유지할 수 있습니다.

 

기본 예제

다음 예제에서는 Print라는 함수 객체를 정의하고, std::for_each 알고리즘을 사용하여 벡터의 각 요소를 출력합니다.

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

struct Print {
    void operator()(int x) const {
        std::cout << x << " ";
    }
};

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 함수 객체 사용
    std::for_each(vec.begin(), vec.end(), Print());
    std::cout << std::endl;

    return 0;
}

이 예제에서 Print 구조체는 operator()를 오버로딩하여 int 값을 출력합니다. std::for_each는 벡터의 각 요소에 대해 Print 객체를 호출합니다.

 

상태를 가지는 함수 객체

함수 객체는 상태를 가질 수 있어 함수 호출 간에 데이터를 유지할 수 있습니다. 다음 예제에서는 Counter라는 함수 객체를 정의하고, 함수 호출 간에 count 상태를 유지합니다.

#include <iostream>

struct Counter {
    int count;

    Counter() : count(0) {}

    void operator()(int x) {
        count += x;
    }
};

int main() {
    Counter counter;

    counter(5);
    counter(10);

    std::cout << "Counter: " << counter.count << std::endl;

    return 0;
}

 

이 예제에서 Counter 구조체는 count 상태를 가지며, operator()를 오버로딩하여 countx 값을 더합니다. main 함수에서 counter 객체는 510을 더해 최종 count 값은 15가 됩니다.


실습 문제

문제 1: 람다 함수를 사용하여 벡터의 짝수 요소만 출력

벡터의 짝수 요소만 출력하는 람다 함수를 작성하세요.

 

해설:

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

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    std::for_each(vec.begin(), vec.end(), [](int x) {
        if (x % 2 == 0) {
            std::cout << x << " ";
        }
    });
    std::cout << std::endl;

    return 0;
}

 

이 예제는 std::for_each 알고리즘과 람다 함수를 사용하여 벡터의 짝수 요소만 출력합니다.

 

문제 2: 함수 객체를 사용하여 벡터의 합계 계산

벡터의 요소 합계를 계산하는 함수 객체를 작성하세요.

 

해설:

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

struct Sum {
    int total;

    Sum() : total(0) {}

    void operator()(int x) {
        total += x;
    }
};

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    Sum sum = std::for_each(vec.begin(), vec.end(), Sum());
    std::cout << "Sum: " << sum.total << std::endl;

    return 0;
}

 

이 예제는 Sum이라는 함수 객체를 정의하고, std::for_each 알고리즘을 사용하여 벡터의 요소 합계를 계산합니다.


이제 1일차의 학습을 마쳤습니다. 람다 함수와 함수 객체에 대해 상세히 학습하고 실습 문제를 풀어보았습니다.

 

질문이나 피드백이 있으면 언제든지 댓글로 남겨 주세요. 내일은 "고급 템플릿 프로그래밍"에 대해 다루겠습니다.

반응형