考虑这个代码(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)
会产生什么结果外,含义没有区别。