게임 개발/C++

[C++] 람다 함수 - 1. 기본 형태

유행성바코드 2025. 3. 25. 20:21

목차

  • 01. Intro
  • 02. 람다 함수
    • 문법
    • 캡처 모드
    • 반환형
  • 03. 마무리
  • 04. 연관 내용

01. Intro

오늘은 [람다 함수]의 기본 형태에 대해 알아보겠습니다.

 


02. 람다 함수

람다 함수는 이름 없이 함수를 정의하고 이를 사용할 수 있도록 지원하는 기능입니다.

보통, 함수를 1회용으로 사용해야 할 때 주로 사용합니다.

 

문법

람다 함수의 기본 형태는 아래와 같습니다.

[캡처](매개 변수){구현부}

함수처럼 ()에 매개 변수 인자를 대입합니다.

그리고, {}는 함수의 기능을 정의하는 구현부입니다.

[]인 캡처는 조금 있다가 알아보겠습니다.

 

    // 람다 함수
    auto add = [](int a, int b) 
    { 
        int result = a + b;
        return result;
    };

위 문법으로 단순 더하기 기능을 하는 람다 함수를 작성하면, 위 코드와 같습니다.

더하기 기능을 가진 람다 함수를 함수 객체로 관리할 수 있습니다.

 

cout << add(4, 5) << endl;

그래서, 추후에 사용자가 호출하고 싶은 시점에서 함수 객체로 람다 함수를 실행할 수 있습니다.

함수 객체는 추후에 다루도록 하겠습니다.

 

#include <iostream>

using namespace std;

int main() 
{
    int num = 10;

    // 람다 함수
    auto add = [](int a, int b) 
    { 
        int result = a + b;
        return result;
    };

    cout << add(4, 5) << endl;
    cout << add(5, 6) << endl;

    return 0;
}

람다 함수의 구현과 실행 부분을 합친 후, 컴파일한 결과는 위 사진과 같습니다.

 

위와 같은 예시 이외에도 알고리즘 문제를 해결할 때, 자주 사용합니다.

특히, sort함수로 특정 조건에 따라 정렬을 할 때, 사용하면 매우 편리합니다.

 

아래 코드는 두 가지 조건을 바탕으로 정렬을 한 예시입니다.

1. 오름차순

2. 홀수가 짝수보다 앞에 위치

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

using namespace std;

int main() 
{
    // i번째 요소는 i값을 가지도록 초기화
    vector<int> nums(10);
    for (int i = 0; i < nums.size(); i++)
    {
        nums[i] = i;
    }

    // 1. 오름차순
    // 2. 홀수가 앞, 짝수는 뒤
    sort(nums.begin(), nums.end(), [](const int a, const int b)
    {
        // 둘 다 홀수
        if (a % 2 == 1 && b % 2 == 1)
        {
            return a < b;
        }
        // 둘 중 하나 홀수
        else if (a % 2 == 1 || b % 2 == 1)
        {
            // a가 홀수 & b가 짝수 -> true : a가 먼저
            // a가 짝수 & b가 홀수 -> false : b가 먼저
            return a % 2 == 1;
        }
        // 둘 다 짝수 
        return a < b;
    });

    for (const int& num : nums)
    {
        cout << num << " ";
    }
    cout << endl;

    return 0;
}

위 코드를 실행하면, 홀수가 앞이고 짝수가 뒤면서, 같은 형태끼리는 오름차순이 적용된 것을 확인할 수 있습니다.

 

캡처 모드

람다 함수의 []는 캡처 모드를 지정할 수 있습니다.

캡처 모드 종류별로 자세히 알아보겠습니다.

 

[ ] 캡처 없음

캡처에 아무것도 적지 않는 경우에는 람다 함수 외부의 변수에 대해 접근할 수 없습니다.

그래서, 매개 변수 인자와 함수 내 지역 변수만 접근할 수 있습니다.

람다 함수 외부의 변수에 대해 접근할 때, 위와 같은 오류가 발생합니다.

 

[=] 값 캡처

값 캡처는 람다 함수가 정의되는 시점에 외부에서 가져온 모든 변수를 복사한 뒤, 람다 내부에서 사용합니다.

 

#include <iostream>

using namespace std;

int main() 
{
    int num = 10;

    auto printNum = [=]() 
    { 
        cout << num << endl; 
    };

    num = 50;

    printNum();

    return 0;
}

그래서, 람다 함수를 정의한 시점 뒤에, num의 값을 50으로 변경하고 람다 함수를 호출했지만, 변경 전인 10이 출력됩니다.

 

[&] 참조 캡처

참조 캡처는 외부에서 가져온 모든 변수를 참조한 뒤, 람다 내부에서 사용합니다.

#include <iostream>

using namespace std;

int main() 
{
    int num = 10;

    auto printNum = [&]() 
    { 
        cout << num << endl; 
    };

    num = 50;

    printNum();

    return 0;
}

값 캡처 모드와는 다르게 변경된 num의 값인 50이 출력됩니다.

이는, num 변수에 대해 참조를 했기 때문에, 값을 변경한 그대로 적용됩니다.

 

매개 변수마다 캡처

위 캡처 모드는 모든 변수에 대해 적용된다는 특징이 있습니다.

하지만, 캡처 공간에는 변수별로 값 캡처와 참조 캡처를 적용할 수 있습니다.

#include <iostream>

using namespace std;

int main() 
{
    int x = 10;
    int y = 100;
    int z = 1000;

    auto printTest = [&x, y, z]() 
    { 
        cout << "x = " << x << endl;
        cout << "y = " << y << endl;
        cout << "z = " << z << endl;
    };

    x = 50;
    y = 500;
    z = 5000;

    printTest();

    return 0;
}

위 람다 함수는 외부 변수 x에 대해서만 참조 캡처를 하고 나머지 변수는 값 캡처를 합니다.

 

위 상황은 아래 코드처럼도 사용할 수 있습니다.

#include <iostream>

using namespace std;

int main() 
{
    int x = 10;
    int y = 100;
    int z = 1000;

    auto printTest = [=, &x]() 
    { 
        cout << "x = " << x << endl;
        cout << "y = " << y << endl;
        cout << "z = " << z << endl;
    };

    x = 50;
    y = 500;
    z = 5000;

    printTest();

    return 0;
}

[=, &x]는 변수 x를 제외한 외부 변수는 모두 값 캡처를 한다는 의미입니다.

 

참고로 순서가 정반대 형태인 [&x, =] 형태는 컴파일이 되지 않습니다.

또한, [&x]만 사용하면, 변수 x만 참조 캡처로 외부에서 가져올 수 있으니, 다른 외부 변수인 y와 z에 대해서는 접근이 불가능합니다.

 

값 캡처처럼 참조 캡처도 적용할 수 있습니다. ex) [&, x]

 

반환형

람다 함수에서 반환 형태는 컴파일러가 추론해서 결정합니다.

하지만, 사용자가 반환형을 명시적으로 작성할 수 있습니다.

[캡처](매개 변수) -> 반환형 {구현부}

 

 

그러면, 이번에는 반환형을 명시적으로 작성한 람다 함수 코드를 확인하겠습니다.

int main()
{
    int num = 10;

    // 람다 함수 1 - 반환형 생략
    auto add_double = [](double a, double b)
    {
        double result = a + b;
        return result;
    };

    // 람다 함수 2 - 반환형을 int로
    auto add_int = [](double a, double b)
    -> int {
        double result = a + b;
        return result;
    };


    cout << "add_double(4.1, 5.2) : " << add_double(4.1, 5.2) << endl;
    cout << "add_int(4.1, 5.2) : " << add_int(4.1, 5.2) << endl;


    return 0;
}

 

두 번째 람다 함수의 실행 결과를 보면, 반환형을 int로 작성함으로써, 소수점이 버려지는 것을 확인할 수 있습니다.

 


03. 마무리

다음 포스팅 글로는 람다 함수를 사용한 활용 예시와 추가 정보에 대해 알아보겠습니다.

 


04. 연관 내용

  • [C++] 람다 함수 - 2. 활용
 

[C++] 람다 함수 - 2. 활용

목차01. Intro02. 람다 함수STL 활용mutable 활용03. 마무리04. 연관 내용01. Intro오늘은 람다 함수를 활용해서 다양한 예시를 확인해 보겠습니다. 02. 람다 함수vector 활용STL의 vector에 있는 데이터를 정렬

epidemic-barcode.tistory.com

 


 

읽어주셔서 감사합니다.

틀린 내용 지적은 언제나 환영입니다!