C++ 초급 - 추가 내용 (심화 학습) (3 - 람다 함수 (lambda expressions))

2025. 2. 22. 18:38프로그래밍 언어/C++

📌 3. 람다 함수 (lambda expressions)

람다 함수(lambda expressions)는 간결한 익명 함수(이름 없는 함수)를 정의하는 기능으로, 콜백 함수, 일회성 함수, 함수 객체의 대체 등 다양한 용도로 활용된다.


📌 3.1 람다 함수 기본 문법 ([](){})

🔹 (1) 람다 함수의 기본 구조

C++의 람다 함수는 다음과 같은 형식으로 작성된다.

[캡처 리스트] (매개변수) -> 반환 타입 { 함수 본문 };

💡 예제: 기본적인 람다 함수

#include <iostream>

int main() {
    auto greet = []() { std::cout << "Hello, Lambda!" << std::endl; };
    greet();  // 람다 함수 호출

    return 0;
}

🔹 출력 결과

Hello, Lambda!

💡 설명

  • [] → 캡처 리스트 (변수를 람다 함수 내부에서 사용하도록 설정)
  • () → 매개변수 목록
  • {} → 함수 본문

📌 3.2 캡처 리스트 ([=], [&], [this]) 활용법

람다 함수 내부에서 외부 변수를 사용하려면 "캡처 리스트"를 활용해야 한다.

🔹 (1) 값 캡처 ([=])

  • 외부 변수 값을 복사하여 사용 (변경 불가)
  • 함수 내부에서 읽기 전용으로 접근 가능

💡 예제: [=]을 이용한 값 캡처

#include <iostream>

int main() {
    int x = 10;
    auto printX = [=]() { std::cout << "x: " << x << std::endl; };
    printX();  // 값 캡처를 통해 x 사용 가능

    return 0;
}

🔹 출력 결과

x: 10

🔹 (2) 참조 캡처 ([&])

  • 외부 변수를 참조(&)로 캡처하여 원본 값을 수정 가능

💡 예제: [&]을 이용한 참조 캡처

#include <iostream>

int main() {
    int x = 10;
    auto modifyX = [&]() { x += 5; };  // x를 참조로 캡처하여 수정 가능
    modifyX();
    std::cout << "x: " << x << std::endl;

    return 0;
}

🔹 출력 결과

x: 15

🔹 (3) 특정 변수만 캡처

  • 특정 변수만 값 또는 참조로 캡처할 수도 있다.

💡 예제: 특정 변수만 캡처

#include <iostream>

int main() {
    int a = 5, b = 10;
    auto captureA = [a]() { std::cout << "a: " << a << std::endl; };
    auto captureB = [&b]() { b += 5; };

    captureA();
    captureB();
    std::cout << "b: " << b << std::endl;

    return 0;
}

🔹 출력 결과

a: 5
b: 15

🔹 (4) this 캡처 ([this])

  • 클래스 멤버 함수를 람다에서 사용할 때 필요

💡 예제: [this]을 이용한 멤버 변수 접근

#include <iostream>

class Example {
    int value = 42;

public:
    void showValue() {
        auto print = [this]() { std::cout << "Value: " << value << std::endl; };
        print();
    }
};

int main() {
    Example ex;
    ex.showValue();

    return 0;
}

🔹 출력 결과

Value: 42

📌 3.3 람다 함수의 반환 타입 (-> Type) 지정 방법

  • 람다 함수의 반환 타입을 명시적으로 지정할 수 있다.

💡 예제: 반환 타입을 -> int로 지정

#include <iostream>

int main() {
    auto add = [](int a, int b) -> int {
        return a + b;
    };

    std::cout << "10 + 20 = " << add(10, 20) << std::endl;

    return 0;
}

🔹 출력 결과

10 + 20 = 30

💡 설명

  • -> int → 반환 타입을 int로 지정

📌 3.4 std::function을 활용한 람다 함수 저장

람다 함수는 std::function을 사용하여 저장하고 나중에 실행 가능하다.

💡 예제: std::function을 이용한 람다 저장

#include <iostream>
#include <functional>

int main() {
    std::function<int(int, int)> multiply = [](int a, int b) { return a * b; };

    std::cout << "3 * 4 = " << multiply(3, 4) << std::endl;

    return 0;
}

🔹 출력 결과

3 * 4 = 12

📌 3.5 C++14의 제네릭 람다 (auto 매개변수)

C++14부터는 매개변수 타입을 auto로 지정 가능.

💡 예제: auto를 사용한 제네릭 람다

#include <iostream>

int main() {
    auto print = [](auto value) { std::cout << "Value: " << value << std::endl; };

    print(10);        // 정수
    print(3.14);      // 실수
    print("Hello");   // 문자열

    return 0;
}

🔹 출력 결과

Value: 10
Value: 3.14
Value: Hello

💡 설명

  • auto를 사용하면 다양한 타입을 처리 가능 (int, double, string 등)

📌 3.6 C++20의 constexpr 람다와 template 람다

🔹 (1) constexpr 람다 (C++20)

C++20에서는 constexpr 람다를 사용하여 컴파일 타임 연산이 가능하다.

💡 예제: constexpr 람다

#include <iostream>

int main() {
    constexpr auto square = [](int x) { return x * x; };
    
    constexpr int result = square(5);  // 컴파일 타임에 계산됨
    std::cout << "5^2 = " << result << std::endl;

    return 0;
}

🔹 출력 결과

5^2 = 25

🔹 (2) template 람다 (C++20)

C++20부터는 람다에서 template을 사용할 수 있음.

💡 예제: template을 사용한 람다

#include <iostream>

int main() {
    auto add = []<typename T>(T a, T b) { return a + b; };

    std::cout << add(3, 4) << std::endl;        // 정수 덧셈
    std::cout << add(3.5, 2.5) << std::endl;    // 실수 덧셈

    return 0;
}

🔹 출력 결과

7
6

📌 4. 정리

개념  설명
캡처 리스트 [=], [&], [this]을 사용하여 외부 변수 접근
반환 타입 지정 -> Type을 사용하여 명시적으로 반환 타입 지정 가능
std::function 활용 람다를 저장하고 실행할 수 있음
제네릭 람다 (C++14) auto 매개변수를 사용하여 다양한 타입 지원
constexpr 람다 (C++20) 컴파일 타임에서 실행 가능
template 람다 (C++20) 템플릿을 활용한 타입 유연성 제공