프로그래밍 언어/C++

C ++ 11에서 람다식이란?

Rateye 2021. 7. 28. 10:21
728x90
반응형
질문 : C ++ 11에서 람다식이 란 무엇입니까?

C ++ 11에서 람다식이 란 무엇입니까? 언제 사용합니까? 도입 전에는 불가능했던 문제의 종류는 무엇입니까?

몇 가지 예와 사용 사례가 유용 할 것입니다.

답변

std::for_eachstd::transform 과 같은 유용한 일반 함수가 포함되어있어 매우 편리합니다. 안타깝게도 특히 적용하려는 펑터 가 특정 기능에 고유 한 경우 사용하기가 매우 번거로울 수 있습니다.

#include <algorithm>
#include <vector>

namespace {
  struct f {
    void operator()(int) {
      // do something
    }
  };
}

void func(std::vector<int>& v) {
  f f;
  std::for_each(v.begin(), v.end(), f);
}

f 한 번만 사용하고 특정 위치에서 사소한 일을 한 번만 수행하기 위해 전체 클래스를 작성하는 것이 과도하게 보입니다.

C ++ 03에서는 functor를 로컬로 유지하기 위해 다음과 같이 작성하고 싶을 수 있습니다.

void func2(std::vector<int>& v) {
  struct {
    void operator()(int) {
       // do something
    }
  } f;
  std::for_each(v.begin(), v.end(), f);
}

그러나 이것은 허용되지 않습니다. f 는 C ++ 03 의 템플릿 함수에 전달할 수 없습니다.

반응형

새 솔루션

C ++ 11에서는 람다를 도입하여 인라인 익명 함수를 작성하여 struct f 를 대체 할 수 있습니다. 작은 간단한 예제의 경우 읽기가 더 깨끗하고 (모든 것을 한곳에 보관) 잠재적으로 유지 관리가 더 간단 할 수 있습니다 (예 : 가장 간단한 형식).

void func3(std::vector<int>& v) {
  std::for_each(v.begin(), v.end(), [](int) { /* do something here*/ });
}

Lambda 함수는 익명의 펑터에 대한 구문 설탕 일뿐입니다.

간단한 경우에 람다의 반환 유형이 추론됩니다. 예 :

void func4(std::vector<double>& v) {
  std::transform(v.begin(), v.end(), v.begin(),
                 [](double d) { return d < 0.00001 ? 0 : d; }
                 );
}

그러나 더 복잡한 람다를 작성하기 시작하면 컴파일러에서 반환 유형을 추론 할 수없는 경우가 빠르게 발생합니다. 예 :

void func4(std::vector<double>& v) {
    std::transform(v.begin(), v.end(), v.begin(),
        [](double d) {
            if (d < 0.0001) {
                return 0;
            } else {
                return d;
            }
        });
}

-> T 사용하여 람다 함수의 반환 유형을 명시 적으로 지정할 수 있습니다.

void func4(std::vector<double>& v) {
    std::transform(v.begin(), v.end(), v.begin(),
        [](double d) -> double {
            if (d < 0.0001) {
                return 0;
            } else {
                return d;
            }
        });
}

"Capturing" 변수

지금까지 우리는 그 안에서 람다에 전달 된 것 이외의 다른 것을 사용하지 않았지만, 람다 내에서 다른 변수를 사용할 수도 있습니다. 다른 변수에 액세스하려면 지금까지이 예제에서 사용되지 않은 []

void func5(std::vector<double>& v, const double& epsilon) {
                                                                                                                                                                                                                                                                     std::transform(v.begin(), v.end(), v.begin(),
                                                                                                                                                                                                                                                                             [epsilon](double d) -> double {
                                                                                                                                                                                                                                                                                         if (d < epsilon) {
                                                                                                                                                                                                                                                                                                         return 0;
                                                                                                                                                                                                                                                                                                                     } else {
                                                                                                                                                                                                                                                                                                                                     return d;
                                                                                                                                                                                                                                                                                                                                                 }
                                                                                                                                                                                                                                                                                                                                                         });
                                                                                                                                                                                                                                                                                                                                                         }
                                                                                                                                                                                                                                                                                                                                                         

참조 및 값으로 캡처 할 수 있으며 각각 &=

  • [&epsilon] 참조로 캡처
  • [&] 는 람다에서 사용되는 모든 변수를 참조로 캡처합니다.
  • [=] 는 람다에서 사용되는 모든 변수를 값으로 캡처합니다.
  • [&, epsilon] 은 [&]와 같은 변수를 캡처하지만 값으로 epsilon을 캡처합니다.
  • [=, &epsilon] 은 [=]와 같은 변수를 캡처하지만 참조로 엡실론을 캡처합니다.

생성 operator() 입니다 const 캡처 될 것이라는 의미로, 기본적으로 const 사용하면 기본적으로 그들에 액세스 할 때. 이것은 동일한 입력을 가진 각 호출이 동일한 결과를 생성하는 효과가 있지만 operator() const 가 아닌 것을 요청하기 위해 람다를 mutable 으로 표시 할 수 있습니다.

출처 : https://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11
728x90
반응형