【问题标题】:Using a switch or defining an array of functions - which is faster?使用开关或定义函数数组 - 哪个更快?
【发布时间】:2017-05-09 19:17:24
【问题描述】:

这两个程序中哪个运行得更快?第一个是指向两个重新分配变量的函数的指针数组,第二个是两种情况的切换,以相同的方式重新分配变量。

1:

#include <iostream>

void w (int &z);
void y (int &z);

int main(int argc, const char * argv[]) {
    void (*p[2]) (int &a) = {w,y};
    int s = 0;
    for(int i=0;i<1000;i++) {
        p[s](s);
    }
    return 0;
}

void w (int &z) {
    z = 1;
}

void y (int &z) {
    z = 0;
}

2:

#include <iostream>

int main(int argc, const char * argv[]) {
    int s = 0;
    for(int i=0;i<1000;i++) {
        switch (s) {
            case 0:
                s = 1;
                break;
            case 1:
                s = 0;
                break;
        }
    }
    return 0;
}

一般来说,如果您在编译时知道根据变量的当前值执行哪些指令,那么如果您使用指向函数的指针数组而不是定义 switch 语句,程序会运行得更快吗?还是 switch 语句更快?还是它们都一样快?

【问题讨论】:

  • 您是否已经测量过自己(开启优化级别)?
  • 第一个例子让我毛骨悚然......
  • 你展示的两个程序并不完全等价,它们没有严格的可比性。
  • switch 版本绝对更具可读性,在许多情况下,这比您从第一个版本中获得的(潜在且不保证的)优化收益更重要。
  • 在性能方面它们很可能是等效的。优化编译器会将合适的 switch 语句转换为跳转表。

标签: c++ arrays performance switch-statement


【解决方案1】:

我认为 switch 语句会更快,因为函数指针具有查找函数和函数调用的开销。 switch 只是一个直接的跳表。

【讨论】:

    【解决方案2】:

    switch 语句会更快,而且更容易理解。至少,在这种情况下。在大多数情况下很可能。

    在这种情况下它会更快,因为编译器可以完全放弃整个循环。很明显,所有代码都只对局部变量有影响,因此可以在不改变程序可观察行为的情况下消除它。

    这突出了为什么switch 语句通常会更快。如果有很多情况,它将使用跳转表来实现,并且编译器可以将所有信息触手可及,并且可以出于速度原因使用各种技巧来删除代码或移动代码。

    对于函数指针版本,编译器必须足够聪明,才能意识到您正在使用函数指针初始化数组,然后永远不要更改它或将其地址传递给任何东西,以便其他任何东西都可以更改它。然后它还必须查看所有被调用的函数,并意识到它们对除了传入的引用之外的任何东西都没有影响。这是一个很多要问的问题。

    更糟糕的是,函数指针版本对于人类来说真的很难理解。如果您不关心这些,为什么不用汇编语言或(甚至更好)原始处理器操作码来编写它?

    【讨论】:

      猜你喜欢
      • 2019-03-20
      • 2016-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-12
      • 1970-01-01
      • 1970-01-01
      • 2014-01-07
      相关资源
      最近更新 更多