C++11 람다 함수는 값 복사 또는 참조로 외부 범위에서 선언된 변수를 캡처한다.
이는 람다의 값 멤버가 이동 전용 타입이 될 수 없음을 의미한다.
C++14에서는 캡처된 멤버를 임의의 표현식으로 초기화할 수 있다.
이를 통해 외부 범위에 해당하는 명명된 변수를 갖지 않고도 값 이동에 의한 캡처와 람다의 임의 멤버 선언을 모두 수행할 수 있다.
이것은 이니셜라이저 표현식을 사용하여 수행됩니다.
auto lambda = [value = 1] {return value;};
람다 함수 lambda는 초기화한 값인 1을 반환한다. 선언된 캡처는 자동으로 이니셜라이저 표현식에서 타입을 추론한다.
이것은 표준 std::move 함수를 사용하여 이동으로 캡처하는 데 사용할 수 있다.
std::unique_ptr<int> ptr(new int(10));
auto lambda = [value = std::move(ptr)] {return *value;};
일반화된 캡처(C++ 14)
C++14에서는 해당 변수가 반드시 람다 함수의 바깥쪽 범위에 존재하지 않아도 캡처 절에 새 변수를 도입하고 초기화할 수 있습니다. 이러한 초기화는 임의의 식으로 표현할 수 있습니다. 새 변수의 형식은 식에서 생성되는 형식에서 추론됩니다. 이 기능을 사용하면 주변 범위에서 이동 전용 변수(예: std::unique_ptr)를 캡처하고 람다에서 사용할 수 있습니다.
pNums = make_unique<vector<int>>(nums);
//...
auto a = [ptr = move(pNums)]()
{
// use ptr
};
Lambda expression을 모르는 사람들을 위해 설명을 추가한다.
C++11에서는 재사용하지 않고 이름을 지정할 가치가 없는 짧은 코드 조각에 사용할 수 있는 인라인 함수를 작성할 수 있도록 람다 표현식을 도입했다.
가장 간단한 형태의 람다 표현식은 다음과 같이 정의할 수 있다.
[ capture clause ] (parameters) -> return-type
{
definition of method
}
일반적으로 람다 식의 return 타입은 컴파일러 자체에서 명시되며 명시적으로 지정할 필요가 없으며 -> return-type 부분을 무시할 수 있지만 조건문과 같이 복잡한 경우 컴파일러에서 반환을 확인할 수 없다. 이 경우에는 유형을 지정해야 한다.
auto square = [](int i)
{
return i * i;
};
cout << "Square of 5 is : " << square(5) << endl;
위의 예제와 같이 return-type을 지정하지 않아도 상관없다.
람다 식은 바깥쪽 범위에서 변수에 엑세스할 수 있으므로 일반 함수보다 더 많은 기능을 가질 수 있다.
세 가지 방법으로 범위를 둘러싸는 외부 변수를 캡처할 수 있다.
1. 참조로 캡처
2. value로 캡처
3. 둘다 캡처(혼합 캡처)
변수 캡처에 사용되는 구문:
[&] : 모든 외부 변수를 참조로 캡처
[=] : value로 모든 외부 변수를 캡처
[a, &b] : value로 캡처하고 참조로 b 캡처
[ ] : 해당 변수에 로컬인 변수에만 액세스 가능
#include <bits/stdc++.h>
using namespace std;
int main()
{
vector<int> v1 = {3, 1, 7, 9};
// 참조로 캡처
auto pushinto = [&] (int m)
{
v1.push_back(m);
};
// 실제로 v1에 10을 저장
pushinto(10);
int N = 5;
// [=]은 모든 외부 변수에 value로 캡처 가능
int count_N = count_if(v1.begin(), v1.end(), [=](int a)
{
return (a >= N);
});
cout << "5보다 큰 숫자의 개수는? : "
<< count_N << endl;
}
//Output : 5보다 큰 숫자의 개수는 3
https://docs.microsoft.com/ko-kr/cpp/cpp/lambda-expressions-in-cpp?view=msvc-170
https://en.wikipedia.org/wiki/C%2B%2B14#cite_note-9
'C++ > C++14' 카테고리의 다른 글
C++14 : 제네릭 람다(Generic lambdas) (0) | 2022.04.15 |
---|---|
C++14 : 숫자 구분자(Digit separators) (0) | 2022.04.15 |
C++14 : 바이너리 리터럴(Binary literals) (0) | 2022.04.15 |
C++14 : 애그리게이트 멤버 초기화(Aggregate member initialization) (0) | 2022.04.15 |
C++14 : 변수 템플릿(Variable templates) (0) | 2022.04.15 |
댓글