![]() |
1
92
你看,从性能的角度来看,在一些实际情况下,比如在一个循环中多次重复调用函数,性能可能一点也不不同。 对于习惯于将C代码看作是由抽象C机器执行的东西的人来说,这听起来可能很奇怪,因为抽象C机器的“机器语言”与C语言本身非常相似。在这种情况下,“默认情况下”对函数的间接调用确实比直接调用慢,因为它正式涉及到额外的内存访问以确定调用的目标。 然而,在现实生活中,代码是由一台真正的机器执行的,并由一个优化编译器编译,该编译器对底层机器体系结构有很好的了解,这有助于它为特定的机器生成最优化的代码。在许多平台上,从一个循环执行函数调用的最有效方法实际上会导致 直接调用和间接调用的代码,导致两者的性能相同。 例如,考虑x86平台。如果我们“字面上”将直接和间接调用转换成机器代码,我们可能会得到这样的结果
前者在机器指令中使用一个立即数操作数,而且通常比后者快,后者必须从某个独立的内存位置读取数据。
请注意,现在重要的部分—循环体中的实际调用—在这两种情况下完全相同。不用说,演出会很精彩 .
甚至有人可能会说,不管听起来有多么奇怪,在这个平台上,直接调用(在
当然,整个事情并不像一般情况下那么容易。编译器必须处理寄存器的有限可用性,别名问题等等,但是像你的例子中那样简单的情况(甚至在更复杂的情况下),上面的优化将由一个好的编译器执行,并且将完全消除循环直接调用和循环间接调用之间的任何性能差异。这种优化在调用C++函数时特别适用,因为在一个典型的实现中,所涉及的指针完全由编译器控制,使其完全了解混叠图像和其他相关的东西。 当然,总是有一个问题,你的编译器是否足够聪明,以优化这样的事情。。。 |
![]() |
2
26
我认为当人们这么说的时候,他们指的是这样一个事实:使用函数指针可能会阻止编译器优化(内联)和处理器优化(分支预测)。然而,如果函数指针是一种有效的方法来完成您正试图做的事情,那么任何其他方法都可能有同样的缺点。 而且,除非函数指针在性能关键型应用程序或速度非常慢的嵌入式系统的紧密循环中使用,否则这种差异很可能是可以忽略不计的。 |
![]() |
3
10
在c/c++api中,最常见的函数指针是回调函数。如此多的api这样做的原因是,编写一个在事件发生时调用函数指针的系统要比其他方法(如消息传递)有效得多。我个人也使用函数指针作为更复杂的输入处理系统的一部分,其中键盘上的每个键都有一个通过跳转表映射到它的函数指针。这允许我从输入系统中删除任何分支或逻辑,只需处理输入的按键。 |
![]() |
4
10
这种说法很可能是错误的。首先,如果使用函数指针的替代方法是
相当地 比只使用一个函数指针慢得多。虽然通过指针调用函数确实有一些(通常可以忽略的)开销,但通常情况下,比较直接函数调用和通过指针调用的区别是不相关的。
不可能的
)要知道,有时这可能是非常非直观的(例如,linux内核开发人员已经开始删除
|
![]() |
5
8
通过函数指针调用函数是 使用函数指针是因为它们可以使程序更简单、更干净、更易于维护(当然,如果使用得当)。这不仅弥补了可能非常小的速度差异。 |
![]() |
6
7
如果需要使用函数指针,请使用它们,因为任何尝试执行相同操作但避免使用它们的操作都会比使用函数指针更慢,更不易维护。 |
![]() |
7
7
不过,看看cqsort比较函数。因为比较函数不能内联并且需要遵循基于堆栈的标准调用约定,所以排序的总运行时间可以是 (更确切地说是3-10倍)对于整数键来说,比直接的内联调用的相同代码慢。
|
![]() |
8
1
答案取决于函数指针的用途,因此也取决于替代方法。如果函数指针被用来实现一个选项,而这个选项是我们的程序逻辑的一部分,并且不能简单地删除,那么将函数指针调用与直接函数调用进行比较是一种误导。尽管如此,我还是会继续进行比较,然后再回到这个想法。 与直接函数调用相比,函数指针调用在禁止内联时最有可能降低性能。因为内联是一种网关优化,我们可以在函数指针比等效的直接函数调用任意慢的情况下:
Code generated
对于
美好的
|
![]() |
Joseph Hales · C#通用对象函数指针,相同地址? 7 年前 |
![]() |
Trytio · 同时处理非成员函数指针和成员函数指针 7 年前 |
![]() |
Ashutosh Tiwari · 无法理解c中的函数指针++ 7 年前 |
![]() |
cxandru · 有没有比传递参数更好的方法来确定方法的行为? 7 年前 |
![]() |
Aryan · 将引用(右值)移动到函数 7 年前 |
![]() |
moha · 将地址存储到函数指针中 7 年前 |