Страницы

Поиск по вопросам

четверг, 5 декабря 2019 г.

Чем конструкция switch плоха?

#switch


Не раз слышал что конструкция switch это плохо. Например вот в этой статье, пункт
10 Но ни разу не слышал почему и когда он плох. Кто что думает по этому поводу?    


Ответы

Ответ 1



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

Ответ 2



На самом деле предубеждение к switch существует с тех времен, когда компиляторы были неоптимизирующими. Тогда switch превращался в огромный набор условных операторов, что нельзя назвать лучшим решением. Зато выглядело это аккуратнее, чем такой же набор if'ов в исходном коде программе. Сейчас же компилятор, когда видит switch использует либо дерево из условных переходов (что-то в духе такого, см. также), либо использует таблицу переходов. В последнем случае создается таблица вида :<адрес перехода> из которой выбирается нужный адрес, по которому лежит соответствующий индексу код. Можно догадаться, что это существенно эффективнее, чем сравнивать каждое значение соответствующего case. Так что теперь switch не очень страшен. С другой стороны, при использовании конструкции switch-case не нужно забывать про особенности работы с ключевыми словами break и default. Некоторые забывают, например, слово break и в результате имеют некорректное выполнение программы (выполняется не только нужный case, но и последующие, пока не встретится break) Что еще хочу сказать. switch хорошо работает с константными целыми или перечислимыми типами. В этом случае компилятор даже может подсказать, что есть проблема. Например, с помощью предупреждения. Например, для gcc: -Wswitch Warn whenever a switch statement has an index of enumerated type and lacks a case for one or more of the named codes of that enumeration. (The presence of a default label prevents this warning.) case labels outside the enumeration range also provoke warnings when this option is used (even if there is a default label). This warning is enabled by -Wall. -Wswitch-default Warn whenever a switch statement does not have a default case. -Wswitch-enum Warn whenever a switch statement has an index of enumerated type and lacks a case for one or more of the named codes of that enumeration. case labels outside the enumeration range also provoke warnings when this option is used. The only difference between -Wswitch and this option is that this option gives a warning about an omitted enumeration code even if there is a default label.

Ответ 3



Плохость или хорошесть конструкции switch зависит от того во что ее превращает компилятор. Проиллюстрирую в псевдокоде: Конструкция switch switch(i) { case 0: do0; case 1: do1; case 2: do2; default: doDefault; } может превратиться, либо в (вариант №1): if(i==0) do0; else if(i==1) do1; else if(i==2) do2; else doDefault; или же в (вариант №2): switch(i) { 0: do0; 1: do1; 2: do2; default: doDefault; } Отличие состоит в том, что в первом варианте с if-else условие проверяется каждый раз, а во втором условие проверяется 1 раз создается таблица переходов. Очевидно, что 2-й вариант реализации быстрее и удобнее. Скажем в Java все именно так и устроено. Да и вообще в более-менее любом нормальном современном компиляторе так и устроено. В древних компиляторах часто реализовывалось через 1-ю конструкцию if-else - оттуда видимо и предубеждение против switch

Комментариев нет:

Отправить комментарий