함수 포인터는 함수를 주소값으로 받아 사용할 수 있는 포인터다.
bool(*ptr)(int,int) = 함수명; // ptr은 포인터명이다. ptr(1,2); // 호출
함수포인터를 통해 간편하게 함수를 특정 함수의 파라미터로 전달할 수 있다.
함수객체는 클래스에서 Operator() 연산자 오버로딩을 통해 구현하는 함수다.
class Funct
void Operator() {
cout << "함수객체" << endl;
}
다음과 같이 객체선언 후 객체 자체를 호출() 하면 함수객체가 호출된다.
Funct func; func(); // "함수객체"
인수 개수에 따라 Generator(발생자), 단항함수, 이항함수 등으로 불린다.
SimpleSort의 3번째 인수로 dn객체를 넣었는데
dn은 Sort함수안에서 cmp(51,829) 형식으로 실행되어
최종적으로 Down의 operator()가 실행되는 것을 유추할 수 있다.
함수객체가 가지는 장점으로서는 함수포인터는 인라인화가 불가능하지만 함수 객체는 인라인화가 가능하다. 하지만 함수 포인터보다 코드 길이가 길어지는 단점이 있다.
람다(Lamda) 함수는 위의 수고를 덜어주기 위해 등장했으며 새로운 문법을 통해 사용할 수 있다.
람다 함수의 선언식은 다음과 같다.
람다 함수를 호출할 때는 함수객체나 포인터와 같이 ()를 통해 호출한다.
다음은 람다 함수를 이용한 간단한 크기비교 예제다.
SimpleSort의 3번째 인자로 []람다식을 선언하였고 Sort 함수 내에서 cmp 템플릿을 이용하여 전달된 람다식을 함수 내에서 호출하는 것을 확인할 수 있다.
auto l3 = [](){return 43;}; cout << l3() << endl; auto l4 = [](){return 44;}(); cout << l4 << endl;
auto l3는 43이 반환되는 람다식의 선언문을 저장하고 있고 함수 형태로 언제든지 호출 할 수 있다.
반면 auto l4는 이미 호출된 람다식의 반환값을 가지고 있고 l4에는 44의 데이터만 존재한다.
겉으로 봐선 헷갈릴 수 있으니 주의하도록 하자.
람다 형식은 조건부로 인라인화가 가능하다.
auto 형으로 람다식을 받을 땐 인라인화가 가능하지만, 함수 포인터로 전달받을 때는 인라인화가 불가능한데 함수 포인터는 다른 주소를 참조할 수 있어서 컴파일러가 어떤 함수가 실행될 지 예측하기 어렵기 때문이다.