Как Switch компилируется в Visual C ++ и насколько он оптимизирован и быстр? - PullRequest
29 голосов
/ 08 апреля 2010

Когда я узнал, что могу использовать только числовые значения в операторах C ++ switch, я подумал, что тогда между ним и группой if-else.

должна быть какая-то более глубокая разница.

Поэтому я спросил себя:

  • (Чем) отличается switch от if-elseif-elseif с точки зрения скорости выполнения, оптимизации времени компиляции и общей компиляции? Я в основном говорю о MSVC здесь.

Ответы [ 2 ]

36 голосов
/ 08 апреля 2010

Переключатель часто компилируется в таблицу переходов (одно сравнение, чтобы выяснить, какой код запускать), или, если это невозможно, компилятор все еще может изменить порядок сравнений, чтобы выполнить двоичный поиск среди значений (журнал N сравнений). Цепочка if-else является линейным поиском (хотя, я полагаю, если все соответствующие значения являются интегральными константами времени компиляции, компилятор в принципе может выполнять аналогичные оптимизации).

7 голосов
/ 19 июля 2010

Операторы Switch часто являются распространенным источником оптимизации компилятора.То есть то, как они обрабатываются, зависит от настроек оптимизации, которые вы используете в своем компиляторе.

Самый базовый (неоптимизированный) способ составления оператора switch - это трактовать его как цепочку операторов if ... else if ....,Обычный способ, которым компиляторы оптимизируют переключатель, - это преобразовать его в таблицу переходов , которая может выглядеть примерно так:

if (condition1) goto label1;
if (condition2) goto label2;
if (condition3) goto label3;
else            goto default;
label1:
  <<<code from first `case statement`>>>
  goto end;
label2:
  <<<code from first `case statement`>>>
  goto end;
label3:
  <<<code from first `case statement`>>>
  goto end;
default:
  <<<code from `default` case>>>
  goto end;
end:

Одна из причин, по которой этот метод быстрее, состоит в том, что код внутри условных выраженийменьше (так что меньше штраф кеша инструкций, если условие неверно предсказано).Кроме того, «провальный» случай становится более тривиальным для реализации (компилятор пропускает оператор goto end).

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

Предупреждение: вложенные таблицы переходовтрудно сгенерировать, и некоторые компиляторы отказываются даже пытаться его создать.По этой причине избегайте вложения switch в другой switch, если для вас важен максимально оптимизированный код (я не уверен на 100%, как MSVC, в частности, обрабатывает вложенные switch es, но руководство компилятора должно сказать вам,).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...