2016-08-24 6 views

ответ

1

Глядя на final switch документов: http://dlang.org/spec/statement.html#FinalSwitchStatement это просто позволяя те же оптимизации, как switch в C (он должен установить метки в коде и просто использовать что-то вроде Гото базирования на значении переменного). switch в D более общий, чем switch в C и не допускает такой оптимизации. Коммутатор из D может использовать инициализированные значения времени выполнения.

+0

Я должен был правильно объяснить себя, я не хотел сравнивать D с C, хотя это хороший момент, я хотел сравнить возможности оптимизации D 'final switch' и' switch' с точки зрения генерации кода , (Исходное сообщение позже отредактировано, чтобы уточнить.) –

+0

Я просто сравнил «конечный выключатель» и «переключатель» с D с «переключателем» с C. «Переключатель» из D может использовать инициализированные значения времени выполнения, поэтому я думаю, что он не может быть реализован через метки/goto. –

+0

Я считаю, что GDC достаточно умен, чтобы обнаружить все оптимизации, которые возможны, когда код D для «switch» оказывается не более общим, чем C. Например, когда имеется большое количество плотных постоянных возможностей, тогда он генерирует скачок Таблица. Но –

6

Короткий ответ: Отсутствует.

Длинный ответ: Основное преимущество final switch над switch является то, что при использовании его со значением типа перечислений, он дает ошибку, когда Вы пропускаете один из членов перечислений, так что вы можете будьте уверены, что вы их охватите. И если перечисление изменяется так, что у него больше членов или меньше, вы узнаете, что вам нужно обновить свой оператор switch.

Помимо этого, семантически, final switch довольно много то же самое, как switch заявление с default случае имеет assert(0) - это просто, что он бросает SwitchError, а не утверждать 0. Эффект по сути тот же, хотя - ваша программа умирает, когда оператору switch присваивается значение, которое не распространяется ни на один из случаев.

Единственная причина, я могу думать, чтобы использовать final switch с чем-нибудь другим, чем перечисление так, что вам не придется писать default случай, когда case заявления должны охватывать все возможные случаи. И учитывая, что, по крайней мере, некоторое время, вы могли бы предоставить более содержательное сообщение с утверждением, чем SwitchError дает вам (No appropriate switch clause found), я был бы склонен утверждать, что было бы лучше иметь явный случай default с assert(0) и сообщение, чем использовать final switch, когда оператор switch не работает в перечислении.

Теперь, что касается вашего вопроса об оптимизации, я не думаю, что есть вероятность, что final switch обеспечивает любые оптимизации по сравнению с обычным switch. Для того, чтобы выбросить SwitchError, когда final switch присвоено значение, которое не покрывается ни одним из операторов case, final switch пришлось бы опустить в нормальный оператор switch с футляром default, который выдает SwitchError.

Таким образом, с точки зрения результирующего кода, нет действительно никакой разницы между final switch и нормальным switch, который имеет default случай, который бросает SwitchError и оптимизация-мудрый, final switch находится в аналогичной лодке к switch заявление с default случай, который утверждает 0 (хотя assert(0), вероятно, более вероятно, приведет к оптимизации, чем бросать SwitchError, потому что компилятор может предположить, что программа будет умирать, когда утверждение явно false, в то время как программа может поймать Error и продолжать, даже если это не должно).

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

Действительно, я бы предположил, что вы используете только final switch, когда имеете дело с типом перечисления с фиксированным набором значений, чтобы вы могли поймать, когда случаи не совпадают с членами перечисления, и что кроме этого , вы просто не используете final switch. Честно говоря, я был удивлен, узнав, что final switch принял что-либо кроме перечислений.

+0

SwitchError не выбрасывается в режиме деблокирования (вот обсуждение этого вопроса: https://issues.dlang.org/show_bug.cgi?id=11051). Без проверок возможны некоторые оптимизации, см., Например, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49054 и https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51513 – jpf