람다 표현식의 개념과 기본 구조
람다 표현식은 C++ 11에서 도입된 기능으로, 익명 함수를 생성하는 간결한 방법을 제공합니다.
이는 함수형 프로그래밍의 개념을 C++에 도입한 것으로, 코드를 더 간결하고 표현력 있게 만들어줍니다.
람다 표현식의 기본 구조는 다음과 같습니다.
[capture clause]
: 람다 함수 외부의 변수를 캡처하는 방법을 지정
(parameters)
: 함수의 매개변수 (선택적)
-> return_type
: 반환 타입 (선택적, 대부분의 경우 컴파일러가 추론 가능)
{ function body }
: 함수의 본문
예를 들어, 다음은 두 정수를 더하는 간단한 람다 표현식입니다.
캡처 절 (Capture Clause)
캡처 절은 람다 함수가 외부 범위의 변수를 어떻게 "캡처"할지 지정합니다.
주요 캡처 방식은 다음과 같습니다.
[]
: 아무것도 캡처하지 않음
[=]
: 모든 외부 변수를 값으로 캡처
[&]
: 모든 외부 변수를 참조로 캡처
[x]
: x를 값으로 캡처
[&x]
: x를 참조로 캡처
[=, &x]
: x만 참조로 캡처하고 나머지는 값으로 캡처
[&, x]
: x만 값으로 캡처하고 나머지는 참조로 캡처
람다와 STL 알고리즘
람다 표현식은 STL 알고리즘과 함께 사용될 때 특히 강력합니다.
예를 들어, std::sort
를 사용할 때 람다를 통해 사용자 정의 비교 함수를 쉽게 제공할 수 있습니다.
제네릭 람다 (C++ 14)
C++ 14부터는 람다의 매개변수 타입을 auto
로 지정할 수 있어, 제네릭 람다를 만들 수 있습니다.
이를 통해 타입에 독립적인 람다를 작성할 수 있습니다.
람다와 클로저
람다 표현식은 클로저를 생성합니다. 클로저는 함수와 그 함수가 참조하는 환경을 포함하는 객체입니다.
이를 통해 함수가 정의된 환경의 상태를 "기억"할 수 있습니다.
mutable 람다
기본적으로 람다는 값으로 캡처된 변수를 변경할 수 없습니다.
mutable
키워드를 사용하면 이를 가능하게 할 수 있습니다.
람다의 성능 고려사항
람다는 일반적으로 인라인화되어 함수 포인터나 std::function보다 더 효율적입니다.
하지만 캡처하는 변수가 많아지면 성능에 영향을 줄 수 있습니다. 대규모 객체를 캡처할 때는 참조 캡처를 고려해볼 수 있습니다.
C++ 17 이후의 람다 기능
- C++ 17 : 람다 캡처에서
*this
의 복사 캡처 가능
- C++ 20 : 템플릿 람다, 캡처되지 않은 람다를 함수 포인터로 변환 가능
실습 : 학생 성적 처리 시스템
학생들의 성적 정보를 처리하는 시스템을 람다를 활용하여 구현해보세요.
- 학생 구조체 정의 (이름, 점수)
- 학생들의 벡터 생성
- 람다를 사용하여 다음 작업 수행
- 점수에 따라 학생 정렬
- 특정 점수 이상인 학생 필터링
- 모든 학생의 평균 점수 계산
연습 문제
- 주어진 벡터에서 짝수만 필터링하여 새로운 벡터를 반환하는 람다 함수를 작성하세요.
- 문자열 벡터를 입력받아 각 문자열의 길이를 기준으로 오름차순 정렬하는 람다 함수를 작성하세요.
참고자료
- C++ 레퍼런스의 람다 표현식 문서 : Lambda expressions
- "Effective Modern C++" by Scott Meyers의 람다 관련 항목
- CppCon 발표 : "C++ Lambda Idioms" by Scott Meyers
- "C++ Templates : The Complete Guide" by David Vandevoorde, Nicolai M. Josuttis, and Douglas Gregor (제네릭 람다와 관련된 고급 주제)