根据Scott Meyers的说法,C++比C更擅长的一个领域是函数对象比函数指针更快。他说这是因为函数对象被内联了,这增加了速度。
我有两个问题:
我们如何验证函数对象是否真的被内联了?我们可以在实践中验证吗?
函数对象的内联是否取决于我们使用的编译器,还是所有编译器都像这样执行?
注:原文中的HTML标签已被保留。
根据Scott Meyers的说法,C++比C更擅长的一个领域是函数对象比函数指针更快。他说这是因为函数对象被内联了,这增加了速度。
我有两个问题:
我们如何验证函数对象是否真的被内联了?我们可以在实践中验证吗?
函数对象的内联是否取决于我们使用的编译器,还是所有编译器都像这样执行?
C++和C标准给编译器留下了很多自由。 编译器可以在每个指令之间计数10亿次,也可以只在整数中包含质数时这样做。
好的“真实”编译器不会这样做。 这是一个实现质量问题。
将函数对象内联到类似于std::sort
的东西中是每个真正的编译器都会做的事情。 在这些情况下,很容易检测出需要内联的内容,因为类型信息随着其代码一起传递。
使用函数指针进行此操作更加困难。 如果将所有内容转换为void*
或char*
指针,则更加困难。
实际上,使用C样式调用qsort
与使用C ++样式调用std::sort
相比可能会导致显着优势。
qsort
大约比std::sort
慢2倍,如此处所示,在对随机排列的整数进行排序的极其简单的情况下。
检查实际的汇编代码输出主要是一个细节,并且工作量很大,回报很少。 使用具体的实际示例可以让您了解影响有多大。
所有3个clang、gcc和MSVC都能够使std::sort
比它们的qsort
明显更快。 由于这是一种简单的优化,而将函数指针优化为内联调用则不是,因此您预计较小的编译器在qsort
方面可能不会比这更好。
qsort
而不是库函数,则编译器可以优化每个实例,尽管使用了函数指针(只要在每次调用时清楚指向哪个函数),结果将与C++中的std::sort
一样快。 - Marc van Leeuwenqsort
调用,它展开为C代码,内联实现qsort(这也是可行的,但更加疯狂)。 - Yakk - Adam Nevraumontstd::sort
更快,因为它既不使用函数对象也不使用函数指针,而是直接比较元素,正如@usr所指出的那样。 - YvesgereYstd::sort
有一组使用 <
进行比较的重载函数,还有一组使用传入的函数对象进行比较的重载函数。将 std::less<void>{}
(less<void>
是一个无状态函数对象,调用 <
)作为第二个函数对象传递给它,结果与第一个仅使用 <
的函数相同(忽略一些奇怪的边界情况)。直接使用 <
并不是它更快的原因,因为使用间接 <
也同样快速。注:(set of) 是指在 C++17 中添加的并行 std::sort
。 - Yakk - Adam Nevraumont
- 我们如何验证函数对象是否已经被内联了?我们可以在实践中验证吗?
可以,检查最终生成的汇编代码。
- 函数对象内联依赖于我们使用的编译器,还是所有编译器都会这样做?
它严重依赖于编译器实现和所使用的优化级别。
因此,并不保证特定的编译器(链接器)会这样做。
不过,通过函数指针进行的调用是无法被内联的。
据他说,函数对象已经被内联了,因此速度有所提升。
在我看来,“函数对象已被内联”更好地理解为(或者听到的,我不知道这个引用来源于哪里):
函数对象可被内联,但通过函数指针进行的调用则不能。
operator()
),才能够内联化。 - Pete Becker