考虑这段代码(godbolt):
#include <iostream>
template<typename F> void call_by_val(F funct)
{
std::cout << "call_by_val(): ";
funct();
}
template<typename F> void call_by_ref(F& funct)
{
std::cout << "call_by_ref(): ";
funct();
}
template<typename F> void call_by_cref(const F& funct)
{
std::cout << "call_by_cref(): ";
funct();
}
void free_funct()
{
std::cout << "free_funct()\n";
}
int main()
{
call_by_val( free_funct );
call_by_ref( free_funct );
call_by_cref( free_funct );
}
所有这三个调用都按预期工作。 如果是免费功能,我不确定在地毯下发生了什么,所以我想知道这三种风格从语义上讲有什么区别。 是否有客观理由选择其中一个而不是其他?
不可能按值传递函数。当函数的参数具有函数类型时,它会自动调整为“指向[函数类型]的指针”。同样,推导会将函数类型衰减为推导前的函数指针类型。
因此,第一次通话中的
F
将是 void(*)()
,而不是 void()
。
在参考重载中,
F
将被推导为void()
。
const
对于函数的引用没有任何意义,因此第二次和第三次调用中的参数都将是 void(&)()
类型。
funct
是函数引用还是函数指针并不重要,因为您可以像直接命名函数一样调用其中任何一个。除了 decltype(funct)
产生的结果之外,含义没有任何区别。