람다 함수

람다 함수 lambda

  • 이름 없는(익명의) 함수 객체
// 람다의 포맷
[capture_list](parameters) -> return_type { ... }

// 예시
// int i를 받고 bool 값을 반환하는 함수 객체
[](int i) -> bool { return i % 2 == 1; }
  • 리턴 타입을 생략하더라도 컴파일러가 자동으로 추측
// 람다의 포맷
[capture_list](parameters) -> { ... }

// 예시
// int i를 받고 bool 값을 반환하는 함수 객체
auto func = [](int i) { return i % 2 == 1; }
func(4); // false

캡쳐 목록 capture list

  • 람다 함수가 스코프 바깥의 로컬 변수에 접근할 수 있도록 도와준다
// 목록에서 2개 이상 지워졌다면 더 이상 지우지 않는 람다 함수 정의
// 그러나 몇개가 지워졌는지는 외부 변수에 정의되어 있다
int num_erased = 0;

// 이때 capture list를 사용한다
vec.erase(std::remove_if(vec.begin(), vec.end(),
                         [&num_erased](int i) {
                           if (num_erased >= 2)
                             return false;
                           else if (i % 2 == 1) {
                             num_erased++;
                             return true;
                           }
                           return false;
                         }),
          vec.end());
print(vec.begin(), vec.end());
  • 위와 같은 방식으로 람다 함수 내에서 외부에서 정의된 변수를 사용할 수 있다
  • &를 붙이지 않으면 num_erased는 원본이 아닌 복사본을 받게 되고, 이때는 const로 받아오기 때문에 값을 변경할 수도 없다
class SomeClass {
  std::vector<int> vec;

  int num_erased;

 public:
  SomeClass() {

    // ...
    // 람다 함수가 멤버 함수에서 사용되고, 
    // 멤버 변수를 사용해야 한다면 어떨까?
    vec.erase(std::remove_if(vec.begin(), vec.end(),
                         [this](int i) {
                           if (this->num_erased >= 2)
                             return false;
                           else if (i % 2 == 1) {
                             this->num_erased++;
                             return true;
                           }
                           return false;
                         }),
              vec.end());
  }
};
  • 위와 같은 상황에서는 this로 SomeClass 자체를 받아와서 사용한다
  • 간단히 정리하면
    • [] : 아무것도 캡쳐 안함
    • [&a, b] : a는 레퍼런스로 캡쳐, b는 (const) 복사본으로 캡쳐
    • [&] : 외부의 모든 변수들을 레퍼런스로 캡쳐
    • [=] : 외부의 모든 변수들을 복사본으로 캡쳐

출처

Categories: ,

Updated: