본문 바로가기
[C++]

[C++] Lambda Expression

by Hevton 2021. 6. 24.
반응형

익명함수. 함수 객체를 생성한다.

함수 포인터와 함수 객체의 장점을 지닌다.

캡쳐기능을 통해서 함수 바깥쪽의 변수들을 접근할 수 있다. ( &, = , 직접 명시 등등)

& 기호를 통해서는 특히 람다함수 안에서도 외부 변수의 값을 변경할 수 있다.

람다로 재귀 호출도 가능

 

int main() {
    
    // Lambda Expression . 익명함수.  C++ 11에서 추가.
    // [캡쳐블럭](매개변수리스트)->리턴타입{함수바디}
    []()->void {}; // 생략가능한건 (), ->, 리턴타입.
    
    []() {}; // 실행문제없.
    [] {}; // 실행문제없.
    
    
    [] {cout << "Hi Lambda!" << endl; }; // 람다 표현식. 맨 끝에 ()를 붙이면 람다표현식 실행됨.
    [] {cout << "Hi Lambda!" << endl; }(); // 출력됨.
    
    auto in = [] {cout << "Hi Lambda!" << endl; };
    in(); // 출력됨.
    
    
    auto in2 = []() { return 5 + 10; };
    cout << in2() << endl; // 출력됨.
    
    
    auto in3 = [](int a, int b) { return a + b; };
    cout << in3(70, 7) << endl; // 출력
    
    
    cout << [](int a, int b) { return a + b; }(5, 10) << endl; // 출력.
    
    
    // 화살표랑 리턴타입을 생략하지 않고 사용해야 할 필요가 있을 경우도 있다. 리턴값의 캐스팅을 필요로할때.
    
    

    // 캡쳐블럭은 람다 함수 안에서, 참조(또는 사용)하려고 하는 바깥변수를 지정한다.
    short c = 5, d = 7;
    // 캡쳐블럭 없이 외부변수 c, d를 람다함수에서 사용할 수 없다. 캡쳐블럭을 지워보면 답이 나온다.
    auto temp = [c, d](float a, int b) -> int {
        return a + b + c + d;
    };
    
    cout << temp(1.9f, 2) << endl; // 출력.
    
    
    auto temp2 = [c, d](float a, int b) -> int {
        c = -11; // 오류. 값으로써 복제하여 캡쳐하는것이지, 변경 자체는 할 수 없음.
        return 0;
    };
    
    
    // 주소 참조 방식.
    auto temp3 = [&c, d](float a, int b) -> int {
        c = -11; // 이렇게 하면 기존의 원본 c값 변경. 포인터처럼 *를 안붙인다는게 특징적이다.
        return 0;
    };
    
    
    // 특이한 점이 있다.
    // 기존에 캡쳐블럭을 비워두면 외부변수값을 사용할 수 없었다.
    auto temp4 = [](float a, int b) -> int {
        return a + b + c + d; // 오류, c랑 d 찾을 수 없음
    };
    // 그런데 이렇게 하면 모든 외부변수를 참조한다. 주소참조기 때문에 call by reference 형태로 동작한다.
    auto temp5 = [&](float a, int b) -> int {
        return a + b + c + d; // 정상 작동.
    };
    // 캡쳐블럭 안에 = 도 들어갈 수 있다. 이렇게 하면 전체 외부변수값을 사용할 수 있다. 마찬가지로 대입은 안된다. 값으로써 복제이기에 call by value 개념은 아니다.
    auto temp6 = [=](float a, int b) -> int {
        return a + b + c + d; // 정상 작동.
    };

    
    // 정리하면
    // = : 전체변수를 값으로 캡쳐, & : 전체변수를 참조로 캡쳐
    

    
    // 람다를 이용한 재귀. 어렵다. function이라는게 필요하고, 캡쳐블럭에 &fact도 넣어줘야한다.
    // 람다에서 재귀를 구현할 때엔 auto 타입으로 추론이 불가능하다.
    // 반드시 대입하려고 하는 함수의 타입이 명시되어야 함.
    // function을 사용하기 위해서는 #include <functional> 이 필요함.
    // 바깥변수를 참조하기 위해 캡쳐블럭을 사용하고, auto로 추정하기 전에 함수 내에서 사용될 수 없으니 function 키워드 사용해야함.
    // function<int(int)> 의미 : <리턴> (매개변수)
    function<int(int)> fact = [&fact](int n)->int {
        if(n <= 1)
            return 1;
        else
            return n * fact(n - 1);
        
    };
    cout << fact(5) << endl;
    
    
    return 0;

}

 

반응형

'[C++]' 카테고리의 다른 글

[C++] constant 함수  (0) 2021.07.05
[C++] 동적 메모리 할당  (0) 2021.06.24
[C++] 함수 포인터  (0) 2021.06.24
[C++] REFERENCE  (0) 2021.06.24
[C++] ENUMERATION  (0) 2021.06.24