[C++] 람다 식(Lambda Expression)

Date:     Updated:

카테고리:

태그:

이 글은 C++의 람다 식(Lambda Expression)을 공부하고 정리한 글입니다.
람다 식은 이름이 없는 함수 개체이다.

람다 식

  • 이름이 없는 함수 개체
  • 내포(nested)되는 함수

    구조

    [<captures>](<parameters>) <specifiers> -> <return_type>
    {
      <body>
    }
    

    캡처 블록(captures)

    • 람다 식을 품는 범위(scope) 안에 있는 변수를 람다 식에 넘겨줄 때 사용
    • 캡처의 종류
      • []
        • 비어 있음. 캡처하지 않음
      • =
        • 값에 의한 캡처. 모든 외부 변수를 캡처함
        • 람다 식 안에서 수정할 수 없음
      • &
        • 참조에 의한 캡처. 모든 외부 변수를 캡처함
      • <변수 이름="">
        • 특정 변수를 값으로 캡처
        • 람다 식 안에서 수정할 수 없음
      • &<변수 이름="">
        • 특정 변수를 참조로 캡처

    매개변수 목록(parameters)

    • 선택 사항
    • 빈 괄호를 생략할 수 있음

    지정자(specifiers)

    • 선택 사항
    • mutable
      • 값에 의해 캡처된 개체를 수정할 수 있게 함

    반환 형(return_type)

    • 선택 사항
    • 반환 형을 적지 않으면 반환문을 통해 유추해줌

    코드 예시

    // 방법 1
    auto noCapture = []() { std::cout << "No capturing example 1" << std::endl; };
    noCapture();
    
    // 방법 2. 바로 실행
    [] { std::cout << "No capturing example 2" << std::endl; }();
    
    float score1 = 80.f;
    float score2 = 20.f;
    
    auto max1 = []() { return score1 > score2 ? score1 : score2; };        // 컴파일 에러
    auto max2 = [=]() { return score1 > score2 ? score1 : score2; };       // OK
    
    auto changeValue1 = [=]()
    {
      score1 = 100.f;     // 컴파일 에러. score1을 수정할 수 없음
    };
    auto changeValue2 = [&]()
    {
      score1 = 100.f;     // OK
    };
    
    auto printValue1 = [score1]
    {
      std::cout << score1 << " / " << score2 << std::endl;    // 컴파일 에러. score2에 접근할 수 없음
    };
    auto printValue2 = [score1, score2]
    {
      std::cout << score1 << " / " << score2 << std::endl;    // OK
    };
    
    auto changeValue3 = [=, &score1]
    {
      score1 = 100.f;                     // 참조에 의한 캡처
      std::cout << score2 << std::endl;   // 값에 의한 캡처
    };
    
    auto add = [](int a, int b)
    {
      return a + b;
    };
    std::cout << add(score1, score2) << std::endl;
    
    auto foo = [score1]()
    {
      std::cout << ++score1 << std::endl;     // 컴파일 에러. score1을 수정할 수 없음
    }
    auto foo = [score1]() mutable
    {
      std::cout << ++score1 << std::endl;     // OK
    }
    

람다 식의 장점

  • 간단한 함수를 빠르게 작성할 수 있음
    auto max = [](float a, float b) { return a > b ? a : b; };
    

람다 식의 단점

  • 함수 재사용성이 낮음
    • 사람들은 보통 함수를 새로 만들기 전에 클래스에 있는 기존 함수를 찾아 봄
    • 람다 함수는 눈에 잘 띄지 않아서 못 찾을 가능성이 높음
    • 그럼 코드 중복이 발생

베스트 프랙티스

  1. 기본적으로, 이름 있는 함수를 쓰자(전통적 방식)
  2. 자잘한 함수는 람다로 써도 괜찮음(한 줄짜리 함수)
  3. 허나 재사용할 수 있는 함수를 찾기 좀 어려움
  4. 정렬 함수 처럼 STL 컨테이너에 매개변수로 전달할 함수들도 좋은 후보


참조

포큐아카데미 C++ 언매니지드 프로그래밍



💻 열심히 공부해서 작성 중이니 오류나 틀린 부분이 있을 경우 
  언제든지 댓글 혹은 메일로 알려주시면 감사하겠습니다! 😸

맨 위로 이동하기

Cpp 카테고리 내 다른 글 보러가기

댓글 남기기