// approach 1
template <typename T>
void f1(T t, int a, int b) {
t(a, b);
}
// approach 2
void f2(void(*g)(int, int), int a, int b)
{
g(a, b);
}
void g (int a, int b)
{
// do something
}
int main()
{
f1([](int a, int b)
{
//do something
}, 1, 2);
f2(&g, 1, 2);
}
我的问题是,f1
和f2
是否遭受相同的间接寻址延迟以获取要执行的函数的地址(假设lambda是作为函数对象实现的)?
如果lambda不是内联怎么办?
注意:我将函数f1声明为模板,以便将参数lambda类型的推论留给编译器(例如,不是强制执行std函数,不确定它是否会产生影响)。
答案 0 :(得分:5)
从概念上讲,编译器应该能够内联lambda体。使用lambda是一个编译时间,这意味着编译器确切地知道你要调用哪个函数,因此它应该能够内联代码。使用函数指针传递的函数直到运行时才真正知道,因此编译器还有很多工作要做,以便尝试查看是否可以内联它。通常,代码没有内联,并且您通过指针有间接。
答案 1 :(得分:3)
f1和f2是否遭受相同的间接寻址延迟以获取要执行的函数的地址(假设lambda是作为函数对象实现的)?
标准没有规定任何有关延迟的保证。但是,lambda调用没有任何理由比调用常规内联函数有更多的延迟。编译器可以在编译时确定生成函数的地址,并且不需要间接。
调用函数指针可能需要间接开销,除非函数已内联扩展,在这种情况下,指针的值可以在扩展上下文中的编译时知道。
如果lambda不是内联怎么办?
您不能声明lambda,并在另一个编译单元中定义它。所有lambdas都是内联的。
注意:我将函数f1声明为模板,以便将参数lambda类型的推论留给编译器(例如,不是强制执行std函数,不确定它是否会产生影响)。
std::function
至少具有与函数指针一样多的开销。