Как скомпилировать коммутатор в Visual C ++ и насколько он оптимизирован и быстро?

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

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

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

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

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

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

     if (condition1) goto label1; if (condition2) goto label2; if (condition3) goto label3; else goto default; label1: <<>> goto end; label2: <<>> goto end; label3: <<>> goto end; default: <<>> goto end; end: 

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

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

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

    Давайте будем гением компьютера.