함수 객체 및 람다 표현식
Coddy C++ 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 104개 중 74번째.
많은 STL 알고리즘은 동작을 사용자 지정하는 호출 가능한 객체를 허용합니다. 지금까지 std::transform과 함께 람다를 사용하는 방법을 살펴보았습니다. 이제 C++에서 호출 가능한 객체를 만드는 두 가지 방법인 functors와 lambda expressions를 모두 알아보겠습니다.
함자(함수 객체)는 operator()를 오버로드하여 인스턴스를 함수처럼 호출할 수 있도록 하는 class입니다:
#include <algorithm>
#include <vector>
#include <iostream>
struct MultiplyBy {
int factor;
MultiplyBy(int f) : factor(f) {}
int operator()(int x) const {
return x * factor;
}
};
int main() {
std::vector<int> nums = {1, 2, 3, 4};
std::vector<int> result(nums.size());
std::transform(nums.begin(), nums.end(), result.begin(), MultiplyBy(3));
// result: {3, 6, 9, 12}
}각 펑터 인스턴스는 생성 시 설정된 멤버 변수를 통해 고유한 독립 상태를 유지할 수 있으며, 이는 일반 함수 호출로는 할 수 없는 일입니다. 하지만 간단한 연산을 위해 클래스를 정의하는 것은 장황합니다. 람다 표현식은 간결한 대안을 제공합니다:
int factor = 3;
std::transform(nums.begin(), nums.end(), result.begin(),
[factor](int x) { return x * factor; });람다 구문은 [capture](parameters) { body }입니다. 캡처 절은 람다가 액세스할 수 있는 외부 변수를 지정합니다. 값을 기준으로 모두 캡처하려면 [=]를, 참조로 모두 캡처하려면 [&]를 사용하고, [factor] 또는 [&factor]처럼 특정 변수를 나열할 수도 있습니다.
람다는 사용자 지정 기준으로 정렬하는 것과 같은 알고리즘을 사용한 일회성 작업에 특히 유용합니다.
std::vector<int> nums = {5, -2, 8, -1};
std::sort(nums.begin(), nums.end(),
[](int a, int b) { return std::abs(a) < std::abs(b); });
// 절댓값 기준으로 정렬됨: {-1, -2, 5, 8}챌린지
쉬움제품 가격에 다양한 할인 전략을 적용하기 위해 functor와 람다 표현식을 모두 보여 주는 가격 계산기를 만들어 보겠습니다.
코드를 두 파일에 나누어 구성합니다:
Discounts.h: 여기에서 할인 functor와 유틸리티 함수를 define합니다.PercentageDiscount라는 functor를 Create하여 할인율을 정수로 저장합니다. 해당operator()는double가격을 받아 할인된 가격을 반환해야 합니다. 예를 들어 $100에 20% 할인을 적용하면 $80을 반환해야 합니다.FixedDiscount라는 또 다른 functor를 Create하여 차감할 고정 금액을double로 저장합니다. 해당operator()는 가격을 받아 고정 금액을 뺀 가격을 반환해야 합니다(단, 0 below로 내려가서는 안 됩니다).printPrices라는 function을 Create하여const std::vector<double>&를 받고, 모든 가격을 공백으로 구분해 출력한 followed by newline을 출력합니다. 각 가격은 소수점 이하 두 자리로 Format합니다.main.cpp: 다섯 개의 inputs를 읽습니다(each on a separate line):- 첫 번째 제품 가격(double)
- 두 번째 제품 가격(double)
- 세 번째 제품 가격(double)
- 적용할 백분율 할인(integer, 예: 20은 20%)
- 고정 할인 금액(double)
세 가격으로 vector를 Create하고 두 가지 접근 방식을 보여 줍니다:
Original prices:를 출력한 followed by 가격 출력PercentageDiscountfunctor와 함께std::transform을 사용하여 할인된 가격의 새 vector를 Create합니다.After percentage discount:를 출력한 followed by 결과 출력- 원래 가격에
FixedDiscountfunctor와 함께std::transform을 사용하여 another vector를 Create합니다.After fixed discount:를 출력한 followed by 결과 출력 - 각 원래 가격을 doubled하는 lambda expression과 함께
std::transform을 사용합니다.Premium prices (doubled):를 출력한 followed by 결과 출력 - lambda와 함께
std::sort를 사용하여 원래 가격을 descending order로 정렬합니다.Sorted (high to low):를 출력한 followed by 정렬된 가격 출력
예를 들어 inputs가 100.00, 50.00, 75.00, 20, 15.00인 경우:
Original prices: 100.00 50.00 75.00
After percentage discount: 80.00 40.00 60.00
After fixed discount: 85.00 35.00 60.00
Premium prices (doubled): 200.00 100.00 150.00
Sorted (high to low): 100.00 75.00 50.00 이 challenge를 통해 할인 금액과 같은 state를 유지하는 functor와, 빠른 inline 연산을 위해 변수를 capture하는 lambda를 비교할 수 있습니다. 두 접근 방식 모두 std::transform 및 std::sort와 같은 STL algorithms와 원활하게 작동합니다.
직접 해보기
#include <iostream>
#include <vector>
#include <algorithm>
#include "Discounts.h"
int main() {
// 입력 읽기
double price1, price2, price3;
int percentageDiscount;
double fixedDiscount;
std::cin >> price1;
std::cin >> price2;
std::cin >> price3;
std::cin >> percentageDiscount;
std::cin >> fixedDiscount;
// 세 개의 가격으로 벡터 생성
std::vector<double> prices = {price1, price2, price3};
// TODO: Print "Original prices:" followed by the prices using printPrices
// TODO: Use std::transform with PercentageDiscount functor
// 결과를 위한 새 벡터 생성
// Print "After percentage discount:" followed by the results
// TODO: Use std::transform with FixedDiscount functor on original prices
// 결과를 위한 새 벡터 생성
// Print "After fixed discount:" followed by the results
// TODO: Use std::transform with a lambda that doubles each original price
// 결과를 위한 새 벡터 생성
// Print "Premium prices (doubled):" followed by the results
// TODO: Use std::sort with a lambda to sort original prices in descending order
// Print "Sorted (high to low):" followed by the sorted prices
return 0;
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 C++ 컴파일러