람다 소개
파이썬에 익숙한 프로그래머라면 람다도 잘 알아야 합니다. 간단히 말해서, 람다는 익명으로 호출 가능한 코드 블록입니다. 새로운 C++11 표준에서 람다의 형식은 다음과 같습니다.
[capture list] (parameter list) -> return type { function body }
보시다시피 4개의 구성 요소가 있습니다.
1. 캡처 목록: 캡처 목록
2. 매개변수 목록: 매개변수 목록
3. 반환 유형: 반환 유형
4. 함수 본체: 실행 코드
이 중 매개변수 목록과 반환 유형은 무시할 수 있습니다.
몇 가지 간단한 예를 살펴보겠습니다.
auto f1 = [] { return 1; }; auto f2 = [] () { return 2; }; cout<<f1()<<'\t'<<f2()<<endl;
캡처 목록
람다의 캡처 목록은 값과 견적을 모두 캡처할 수 있습니다.
캡처 값:
int test_data[] = {1, 5, 9, 7, 3, 19, 13, 17}; int border = 8; auto f3 = [border](const int &i){ if(i > border) cout<<i<<'\t'; }; for_each(begin(test_data), end(test_data), f3); cout<<endl;
캡처 참조:
auto f4 = [&border](const int &i){ if(i > border) cout<<i<<'\t'; }; border = 6; for_each(begin(test_data), end(test_data), f4); cout<<endl;
출력에서 볼 수 있듯이 테두리가 작동합니다. 람다에서는 수정된 6으로 캡처가 실제로 참조임을 확인합니다.
참조를 캡처할 때 람다가 호출될 때 이 참조가 여전히 유효한지 확인해야 한다는 점에 유의해야 합니다.
캡처 목록은 암시적 캡처를 사용할 수도 있습니다. 이를 통해 컴파일러는 람다 실행 코드를 통해 캡처해야 하는 지역 변수를 결정할 수 있습니다.
암시적 캡처는 값, 참조 또는 이 둘의 혼합을 캡처할 수 있습니다.
char space = ' '; auto f5 = [=](const int &i){ if(i > border) cout<<i<<'\t'; }; auto f6 = [&](const int &i){ if(i > border) cout<<i<<'\t'; }; auto f7 = [&, space](const int &i){ if(i > border) cout<<i<<space; }; border = 0; for_each(begin(test_data), end(test_data), f5); cout<<endl; for_each(begin(test_data), end(test_data), f6); cout<<endl; for_each(begin(test_data), end(test_data), f7); cout<<endl;
여기에서 f7이 사용하는 혼합 형식은 "공간에 추가"로 읽을 수 있습니다. 값을 캡처하고 다른 변수는 참조를 캡처합니다."
변수 람다
람다가 값에 의해 캡처된 변수의 값을 수정해야 하는 경우 가변 키워드를 람다에 추가해야 합니다. 그렇지 않으면 컴파일 오류가 발생합니다.
auto f8 = [&, space](const int &i) mutable { if(i > border) {cout<<i<<space; space='\t';} }; for_each(begin(test_data), end(test_data), f8); cout<<endl; cout<<1<<space<<2<<endl;
출력에서 볼 수 있듯이 첫 번째 호출 후 람다 f8의 공백 값은 탭 문자 Tab으로 바뀌었지만 람다 외부에는 여전히 공백이 있습니다. 공간.
반환형
람다의 반환형은 tail return형 방식을 채택하고 있다. 일반:
1. 람다에 return 문만 포함된 경우 컴파일러는 반환 유형을 추론할 수 있으며 반환 유형을 명시적으로 지정할 필요가 없습니다.
2. 그렇지 않으면 compile 컴파일러는 람다가 void를 반환하고 void를 반환하는 함수는 특정 값을 반환할 수 없다고 가정합니다. 이는 대부분의 경우 모순이므로 반환 유형을 명시적으로 지정해야 합니다.
그러나 실제 테스트 후에는 현재 g++ 컴파일러가 더 똑똑해졌습니다. 포인트 2의 경우 컴파일러가 람다 함수 본문에서 함수의 반환 유형을 추론할 수 있는 한, 그럴 필요가 없습니다. 공식은 반환 유형을 명시적으로 지정합니다. 예:
auto f9 = [](const int i){if(i % 3) return i * 3; else return i;}; transform(begin(test_data), end(test_data), begin(test_data), f9); border = 0; for_each(begin(test_data), end(test_data), f6); cout<<endl;
람다 코드 블록에는 여러 개의 반환 문이 있고 if/else 문도 있지만 컴파일러는 다음을 기반으로 추론할 수 있습니다. 반환하는 return 문 값은 int 유형이어야 하므로 후행 반환 유형을 생략할 수 있습니다.
단, 다음 형식에서는 컴파일러가 반환 유형을 유추할 때 불일치를 발견하므로 반환 유형을 명시적으로 지정해야 합니다.
auto f10 = [](const int i) -> double {if(i % 5) return i * 5.0; else return i;}; transform(begin(test_data), end(test_data), begin(test_data), f10); for_each(begin(test_data), end(test_data), f6); cout<<endl;
요약
1. 람다 표현식 형식: [캡처 목록] (매개변수 목록) -> 반환 유형 { 함수 본문 }, 여기서 매개변수 목록과 반환 유형은 생략 가능합니다.
2. 캡처 목록은 값 [val] 또는 참조 [&ref]를 캡처할 수 있습니다.
3. 캡처 목록은 로컬 변수를 암시적으로 캡처할 수도 있습니다. 또한 값 캡처[=]와 참조 캡처[&]의 두 가지 방법을 혼합할 수도 있습니다. [&, val] 또는 [=, &ref]를 캡처합니다.
4. 람다가 캡처한 값을 수정해야 하는 경우 mutable 키워드를 추가해야 합니다.
4. 람다가 반환 값 유형을 자동으로 유추할 수 없는 경우 반환 유형을 뒤에 명시적으로 지정해야 합니다.
위 내용은 C++11의 새로운 기능인 람다 표현식의 전체 내용입니다. 이 글이 C++를 배우는 모든 분들께 도움이 되었으면 좋겠습니다.
C++11의 새로운 기능을 간략하게 분석한 람다 표현식과 관련된 더 많은 기사를 보려면 PHP 중국어 웹사이트를 주목하세요!