개발자/개발

[C++] 람다 표현식

naheesu 2025. 3. 21. 10:58

📌 C++ 람다 표현식(Lambda Expression)

C++에서 람다 표현식(lambda expression)**은 익명 함수(Anonymous Function)를 생성하는 기능이다.
즉, 함수의 이름 없이 즉석에서 정의하고 사용할 수 있는 간단한 함수이다.

📢 기존의 함수 포인터나 std::function보다 간결하게 함수를 정의하고 사용할 수 있음!


✅ 람다 표현식 기본 문법

[캡처](매개변수) -> 반환형 { 함수 본문 };

 

요소 설명
[] 캡처(Capture): 람다 내부에서 외부 변수 접근 여부 지정
() 매개변수(Parameter): 일반 함수처럼 매개변수 지정
-> 반환형 (선택 사항) 반환형 명시 (auto로 생략 가능)
{} 함수 본문(Body): 람다에서 실행할 코드

✅ 기본적인 람다 표현식 예제

🔹 가장 단순한 형태의 람다

#include <iostream>

int main() {
    auto hello = []() { std::cout << "Hello, Lambda!" << std::endl; };
    hello(); // 결과: Hello, Lambda!
    
    return 0;
}

✔ hello 변수에 람다 표현식을 저장하고, hello();를 호출하여 실행.


🔹 매개변수와 반환값을 가지는 람다

#include <iostream>

int main() {
    auto add = [](int a, int b) -> int { return a + b; };
    
    std::cout << add(3, 4) << std::endl;  // 결과: 7
    return 0;
}

[] 내부에는 캡처 리스트가 없고, (int a, int b)매개변수
-> int반환형 지정 (생략 가능)
✔ { return a + b; }는 함수 본문


✅ 캡처 리스트(Capture)

람다 표현식 내부에서 외부 변수에 접근하려면 캡처 리스트를 사용해야 한다.

1️⃣ 값으로 캡처(=)

#include <iostream>

int main() {
    int x = 10;
    
    auto lambda = [=]() { std::cout << "x: " << x << std::endl; };
    lambda();  // 결과: x: 10

    return 0;
}

✔ [=]은 외부 변수 x를 값으로 복사하여 사용 (읽기 전용)
✔ 람다 내부에서 x의 값을 변경할 수 없음.


2️⃣ 참조로 캡처(&)

#include <iostream>

int main() {
    int x = 10;
    
    auto lambda = [&]() { x += 5; };
    lambda();
    
    std::cout << "x: " << x << std::endl;  // 결과: x: 15
    return 0;
}

✔ [&]은 외부 변수를 참조로 캡처하여 람다 내부에서 수정 가능.
✔ x가 원본 변수의 값을 직접 변경함.


3️⃣ 특정 변수만 캡처

#include <iostream>

int main() {
    int a = 5, b = 10;
    
    auto lambda1 = [a]() { std::cout << "a: " << a << std::endl; };
    auto lambda2 = [&b]() { b *= 2; };
    
    lambda1();  // 결과: a: 5
    lambda2();
    
    std::cout << "b: " << b << std::endl;  // 결과: b: 20
    return 0;
}

✔ [a] → 변수 a만 값 복사
✔ [&b] → 변수 b만 참조 캡처


4️⃣ 혼합 캡처

#include <iostream>

int main() {
    int a = 3, b = 5;
    
    auto lambda = [=, &b]() { b += a; };
    lambda();
    
    std::cout << "b: " << b << std::endl;  // 결과: b: 8
    return 0;
}

✔ [=, &b] → 기본적으로 값 캡처(=), 하지만 b는 참조 캡처(&b)
✔ b만 원본 값 변경 가능, a는 읽기 전용


✅ 람다와 std::function

람다는 std::function과 함께 사용 가능하다.

#include <iostream>
#include <functional>

int main() {
    std::function<int(int, int)> func = [](int a, int b) { return a + b; };
    
    std::cout << func(3, 4) << std::endl;  // 결과: 7
    return 0;
}

✔ std::function을 사용하면 람다를 일반적인 함수 포인터처럼 다룰 수 있음.


✅ 람다 표현식과 mutable

기본적으로 람다는 값 캡처(=)를 사용하면 캡처한 변수를 변경할 수 없음.
하지만 mutable 키워드를 사용하면 변경 가능하다.

#include <iostream>

int main() {
    int x = 10;
    
    auto lambda = [x]() mutable { x += 5; std::cout << "x: " << x << std::endl; };
    lambda();  // 결과: x: 15
    
    std::cout << "Original x: " << x << std::endl;  // 결과: Original x: 10
    return 0;
}

✔ mutable을 사용하면 람다 내부에서 x의 값을 변경 가능
✔ 하지만 원본 변수(x)는 그대로 유지됨!


✅ 람다를 반환하는 함수

람다를 반환하려면 반환형을 auto 또는 std::function으로 설정해야 한다.

1️⃣ auto 반환

#include <iostream>

auto getLambda() {
    return [](int x) { return x * 2; };
}

int main() {
    auto func = getLambda();
    std::cout << func(10) << std::endl;  // 결과: 20
    return 0;
}

2️⃣ std::function 사용

#include <iostream>
#include <functional>

std::function<int(int)> getLambda() {
    return [](int x) { return x * 2; };
}

int main() {
    std::function<int(int)> func = getLambda();
    std::cout << func(10) << std::endl;  // 결과: 20
    return 0;
}

✔ std::function을 사용하면 반환되는 람다의 타입을 명확하게 지정 가능


🔥 결론

람다 표현식이름 없는 함수(익명 함수)를 정의하는 문법
캡처 리스트([])를 사용하여 외부 변수 접근 가능
값 캡처(=), 참조 캡처(&), 특정 변수 캡처 가능
✅ mutable 키워드를 사용하면 값 캡처 변수도 변경 가능
std::function을 사용하면 람다를 더 유연하게 활용 가능

🚀 람다 표현식을 활용하면 코드가 더 간결해지고 가독성이 좋아진다!