Unary Function 은 인자가 1개이며 아무 반환값을 갖는 함수를 말한다.
int test1(int a) ;
char test2(string strText) ;
void test3(char* p) ;
위 세 함수 모두 Unary Function 타입이다.
한마디로, 한개의 인자를 가진 함수이다.
c++ std::for_each 함수의 원형은 아래와 같다.
namespace std {
template<class InputIt, class UnaryFunction>
UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f);
}
복잡한 거 빼고,
위에 적혀있는 Unary Function 에, 한개의 인자를 가진 함수를 변수로 가진다 할 수 있겠다.
아래는 예제이다.
♣ for_each() + 함수포인터
#include <cstdio>
#include <algorithm>
using namespace std ;
int printList(int a)
{
printf("a : %d\n", a) ;
return 1 ;
}
int main()
{
int data[5] = {3, 5, 1, 13, 7} ;
// Unary Function - printList
// by 함수포인터를 사용한 방법
for_each(&data[0], &data[4], &printList) ;
return 1 ;
}
printList 함수는 한개의 인자를 가진 함수이므로 Unary Function 이다.
이 함수를 for_each() 함수의 세번째에 함수포인터로 전달하고 있다.
그러면 for_each() 함수는 data 배열의 값을 하나씩 printList 함수의 인자로 전달하고,
그 값이 전달될 때마다 printList() 함수는 호출된다.
♣ for_each() + 함수객체 (Functor)
함수객체는 굵고 짧게 얘기하면, 클래스 객체를 함수처럼 사용하겠다는 말이다.
예를 들어 아래처럼 test 란 클래스 객체를 생성했다 치자.
MyTest test = MyTest() ;
이 때, test 객체는 보통 아래처럼 쓰인다.
test.init() ;
test.destroy() ;
그런데 함수 객체(Functor) 처럼 구현되면 아래처럼 호출할 수 있다.
test(5) ;
test 는 분명 MyTest 클래스의 객체인데 마치 함수처럼 사용되고 있는 것이다.
대단하게 썼지만 연산자 오버로딩으로 구현했을 뿐이다.
본론으로 돌아와서,
Unary Function 에는 위 함수객체 또한 포함된다.
아래는 그 예제이다.
#include <cstdio>
#include <algorithm>
using namespace std ;
class TotalSum
{
public :
int getSum(){ return sum; } ;
// 아래 구현된 연산자 오버로딩으로 객체를 함수처럼 사용할 수 있다.
void operator() (int x)
{
sum += x ;
}
private :
int sum ;
};
int main()
{
int data[5] = {3, 5, 1, 13, 7} ;
// 함수 객체 (Functor) 를 이용한 방법
// for_each 함수의 반환값은 Unary Function 이다.
// 함수포인터의 경우, 이 반환값은 무시된다.
// 하지만 함수객체는 아래처럼 반환값을 받을 수 있다.
TotalSum temp = TotalSum() ;
TotalSum sum1 = for_each(&data[0], &data[5], temp) ;
printf("Sum1 : %d\n", sum1.getSum()) ;
// 굳이 클래스객체를 생성해서 넘기지 않아도 된다.
TotalSum sum2 = for_each(&data[0], &data[5], TotalSum()) ;
printf("Sum2 : %d\n", sum2.getSum()) ;
return 1 ;
}
♣ for_each() + 람다함수 ( Lamda Function)
함수포인터, 함수객체의 경우, main 함수 밖에서 따로 구현된 코드가 존재한다.
람다함수를 사용하면 for_each() 세번째 인자에서 바로 함수를 구현하여
코드를 직관적으로 짤 수 있고 inline 처럼 구현되어 프로그램 실행속도도 빨라진다고 함.
람다함수는 나도 아리까리해서 그냥 예제로 퉁친다.
#include <cstdio>
#include <algorithm>
using namespace std ;
int main()
{
int data[5] = {3, 5, 1, 13, 7} ;
// Lamda 함수를 이용한 방법
// Lamda 함수는 함수객체처럼 누적된 변수를 가질 수 없다.
// C++14 이상의 mutable 을 사용하거나 외부 변수를 사용한다.사용한다
// 아니면 위와 같이 합을 구하는 경우, accumulate() 함수를 사용할 수 있다.
// 아래는 Lamda 함수를 사용해 값을 출력하는 방법이다.
// 한줄 출력
for_each( &data[0], &data[5], [](int a) { printf("a1 : %d\n", a);});
printf("===================\n") ;
// 인자 분해.
for_each(
&data[0],
&data[5],
[](int a)
{
printf("a2 : %d\n", a);
}
);
return 1 ;
}
몇년 전, 당췌 봐도 뭔소리인지 모르던 개념 (Unary Function, functor, 람다함수 등) 이
이제야 살짝 이해가 가서 정리해 본다.
'삽질미학 > C,C++' 카테고리의 다른 글
정규 표현식 모음 (0) | 2024.09.19 |
---|---|
2차원 벡터를 포인터로 넘겨 사용하기 (0) | 2024.02.13 |
Windows API에서 UTF-8, ANSI(CP949), Unicode 간 변환 개념잡기 (0) | 2021.01.28 |
함수 strtok() 의 대안, strsep() (0) | 2018.07.12 |
[C++] 삼각형 구조의 하향식 길찾기 (0) | 2017.07.18 |