람다 표현식

 

함수의 익명 표기법이다.

일급 함수 및 순수 함수를 만들 때 용이하다.

 

람다식은 크게 캡처 목록 [], 매개변수 목록 (), 본문 {} 3가지로 구성되어있다.

 

간단한 함수를 람다로 표현하기

한 번만 실행되는 한 줄짜리 간단한 함수의 경우 클래스의 멤버 함수나 전역 함수로 만들기보다는 사용되는 곳에 직접 정의하면 가독성 향상 및 최적화될 가능성이 높아진다.

 

std::for_each(std::begin(vehicles), std::end(vehicles), PrintOut); /* 기존 방법 */

std::for_each(std::begin(vehicles),
              std::end(vehicles),
              [](const Vehicle &vehicle) {
                  std::cout << vehicle.GetType << '\n';
              });

 

 

여러 줄의 함수를 람다로 표현하기

한줄 뿐만 아니라 여러줄의 함수도 람다 표현식으로 만들 수 있다.

 

std::for_each(std::begin(vect),
              std::end(vect),
              [](int n) {
                  std::cout << n << " is";
                  if (n < 2) {
                      if (n == 0) std::cout << " not";
                  }
                  else {
                      for (int j = 2; j < n; ++j) {
                          if (n % j == 0) {
                              std::cout << " not";
                              break;
                          }
                      }
                  }
                  std::cout << " prime number" << '\n';
              });

 

 

람다 표현식에서 값 반환

std::transform(std::begin(vect2),
               std::end(vect2),
               begin(vect3),
               [](int n) -> double {
                   return n / 2.0;
               });

 

람다 표현식에서 값 반환시 타입 명시가 필요하다면 매개 변수와 본문 사이에 명시해주면 된다.

명시하지 않으면 컴파일러가 추정한다.

 

 

람다 표현식에서 값 캡처하기

[=](int){ ... }; // 외부 변수 값 복사
[&](int){ ... }; // 외부 변수 참조
[=, &a](int){ ... }; // 외부 변수 값 복사. 단, a만 참조

 

외부 변수를 값 복사로 캡처하면 const화 되기때문에 수정이 불가능하다.

하지만 값을 수정하되 외부에 영향을 미치지 않고 싶다면(call by value) mutable 키워드를 추가하면 된다.

 

int a = 1;
int b = 2;

std::for_each(std::begin(vect),
              std::end(vect),
              [=](int& x) mutable {
                  int old = a;
                  a = b;
                  b = old;
              });

 

덧붙여서 [=], [&] 같은 암시적 캡처의 사용은 절대적으로 지양하는것이 좋다. 필요한 것만 명시적으로 캡처해야한다.

 

 

초기화 캡처

C++14부터 추가된 기능이다.

외부 변수의 값을 캡처해서 람다 표현식의 변수에 할당할 수 있다.

 

int a = 5;
auto myLambda = [&x = a]() { x += 2; }; /* 람다에서 사용하는 x에 a값을 대입한다 */
myLambda();
std::cout << a << '\n'; /* 람다식에 의해 2가 증가했으므로 7이 출력된다 */

 

외부 변수 참조 캡처와 같아보이지만 복사가 불가능한 unique_ptr같은 이동 전용 변수도 캡처하여 람다에서 사용할 수 있다.

 

pNums = std::make_unique<std::vector<int>>(nums);
auto a = [ptr = std::move(pNums)]() { ... }; /* 단순히 pNums를 값으로 캡처하면 오류가 발생한다 */

 

위와 같은 경우는 캡처될 때 move가 사용되었으므로 pNums는 empty가 된다.

 

제너릭 람다 표현식

C++14부터 람다 표현식의 매개변수에 auto 타입이 사용가능해졌다.

 

auto findMax = [](auto &x, auto &y) { return x > y ? x : y; };

 

 

추가로 C++17부터는 캡처 목록에 *this를 사용해서 객체의 복사본을 캡처할 수 있다.

또한 람다 표현식으로 constexpr 객체를 컴파일 타임에 생성할 수 있다.

 

constexpr

객체나 함수 앞에 붙일 수 있는 키워드. 해당 객체나 함수의 반환값을 컴파일 타임에 알 수 있다는 의미를 명시한다.

 

+ Recent posts