在有效的STL中,Scott Meyers在2001年提出建议:
第46项:考虑函数对象而不是函数作为算法参数
在上述章节中,他继续解释inline operator()
可以内联到算法的主体中,但通过函数通常不能。这是因为我们实际上传递了一个函数指针。
支持我seem to remember,如果有人使用函数的地址,则无法内联函数。
这里有两个问题。首先,C ++ 14仍然如此吗?
如果是:
答案 0 :(得分:7)
C ++ 14仍然如此吗?
取决于编译器是否可以内联整个算法。如果可以,那么它也可以内联函数调用。如果没有,那么函数可能无法内联,因为在这种情况下的算法是使用函数指针类型实例化的,因此必须能够处理该类型的所有函数指针。
例如,g ++可以内联一个简单的算法,如std::transform
但不是std::sort
。
没有捕获的lambda可以转换为函数指针,而捕获lambda只能作为仿函数传递。这是否意味着我们只需要为了在最佳优化中说明而捕获某些内容?
没有。没有捕获的lambda仍然是一个算符;使用闭包类型(lambda的类型)而不是函数指针类型来实例化算法。
答案 1 :(得分:5)
为了支持这一点,我似乎记得如果一个函数的地址被采用,那么该函数就无法内联。
你读错了。如果编译器可以跟踪函数指针,则可以将函数内联到任何直接调用站点和任何间接调用站点。 GCC联机帮助页所说的是,内联到每个调用站点的函数根本不会作为单独的函数发出(因此减少二进制大小),除非其地址被采用。
首先,C ++ 14仍然如此吗?
是。当然,现在你通常会写lambda而不是手工制作的算符。
为什么没有自动执行此操作的机制。
这是类型系统的问题。具有给定签名的所有函数具有相同的类型。因此,传递函数指针的算法被实例化为一个具体函数,其代码只在C ++的编译模型中存在一次。
当然,优化器仍然可以在一个特定参数上专门化该函数,但这是一种比仅仅内联函数更高级的优化。所以是的,有一种机制,它不太可能被使用。
这是否意味着我们只需要为了在最佳优化中说明而捕获某些东西?
没有。转换为函数指针是可能的,但除非您显式调用它,否则在将lambda传递给算法时将无法完成。