그 이유는 람다는 함수 객체 이므로 함수 템플릿으로 전달하면 해당 객체에 대한 새로운 함수가 인스턴스화되기 때문입니다. 따라서 컴파일러는 람다 호출을 간단하게 인라인 할 수 있습니다.
반면 함수의 경우 오래된주의 사항이 적용됩니다. 함수 포인터 가 함수 템플릿으로 전달되고 컴파일러는 전통적으로 함수 포인터를 통해 호출을 인라인하는 데 많은 문제가 있습니다. 그들은 수 이론적으로 인라인 될 수 있지만, 주변 기능뿐만 아니라 인라인 될 경우에만 가능합니다.
예를 들어 다음 함수 템플릿을 고려하십시오.
template <typename Iter, typename F>
void map(Iter begin, Iter end, F f) {
for (; begin != end; ++begin)
*begin = f(*begin);
}
다음과 같이 람다로 호출하십시오.
int a[] = { 1, 2, 3, 4 };
map(begin(a), end(a), [](int n) { return n * 2; });
이 인스턴스화 결과 (컴파일러가 작성) :
template <>
void map<int*, _some_lambda_type>(int* begin, int* end, _some_lambda_type f) {
for (; begin != end; ++begin)
*begin = f.operator()(*begin);
}
… 컴파일러는 _some_lambda_type::operator ()
이를 쉽게 알아서 호출 할 수 있습니다. (그 함수 호출 map
과 임의 의 새로운 인스턴스 생성하는 다른 람다 map
각, λ는 구별 타입을 갖기 때문에).
그러나 함수 포인터로 호출하면 인스턴스화는 다음과 같습니다.
template <>
void map<int*, int (*)(int)>(int* begin, int* end, int (*f)(int)) {
for (; begin != end; ++begin)
*begin = f(*begin);
}
… 여기에서 f
호출 할 때마다 다른 주소를 가리 키 map
므로 컴파일러가 f
주변 호출을 인라인 하지 않으면 컴파일러가 호출을 인라인 할 수 없으므로 map
컴파일러가 f
특정 함수로 해석 할 수 있습니다 .