2016-12-24 2 views
-2

Какая из этих двух программ работает быстрее? Первый - это массив указателей на две функции, которые повторно назначают переменную, вторая - это переключатель из двух случаев, которые переписывают переменную таким же образом.Использование переключателя или определение массива функций - что быстрее?

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 быстрее? Или они оба так же быстро?

+7

Вы уже измеряли себя (с включенными уровнями оптимизации)? –

+1

Этот первый пример делает мою кожу сканирующей ... – DeiDei

+0

Две программы, которые вы показываете, на самом деле не эквивалентны, они не являются строго сопоставимыми. –

ответ

1

Я думаю, что операторы switch будут быстрее, потому что указатели на функции имеют накладные расходы на поиск функции и вызов функции. Переключатель - это просто скачкообразный стол.

1

Операция switch будет быстрее, и черт легко понять. По крайней мере, в этом случае. И, вероятно, в большинстве случаев.

В этом случае это будет быстрее, потому что компилятор может полностью отказаться от всего цикла. Очевидно, что весь код влияет только на локальные переменные и поэтому его можно устранить без изменения наблюдаемого поведения программы.

И это подчеркивает, почему оператор switch будет, как правило, быстрее. Если есть много случаев, он будет реализован с помощью таблицы перехода, и компилятор имеет всю информацию прямо у себя под рукой и может делать всевозможные трюки, чтобы сбросить код или переместить его по соображениям скорости.

С версией указателя на функциональность компилятор должен быть достаточно умным, чтобы понять, что вы инициализируете массив указателями на функции, а затем никогда не меняете его и не передаете его адрес ни на что, чтобы все остальное могло его изменить. Затем он также должен заглянуть во все вызываемые функции и понять, что они не влияют ни на что, кроме ссылки. Это лот, чтобы спросить.

И что еще хуже, версия указателя функции действительно трудно понять человеку. И если вас это не волнует, почему вы не пишете его на языке ассемблера или (еще лучше) в операционных кодах необработанных процессоров?