Как я могу обойти отсутствие наконец блок в PHP?

В тех случаях, когда большинство меток case являются последовательными, компиляторы часто обрабатывают операторы switch, чтобы использовать таблицы переходов, а не сравнения. Точные средства, с помощью которых компиляторы решают, какую форму вычисляемого перехода использовать (если есть), будут различаться в разных реализациях. Иногда добавление дополнительных случаев в оператор switch может повысить производительность за счет упрощения сгенерированного кода компилятором (например, если код использует случаи 4-11, тогда как случаи 0-3 обрабатываются по умолчанию, добавление явного case 0:; case 1:; case 2:; case 3:; до default: может В результате компилятор сравнивает операнд с 12 и, если он меньше, использует таблицу переходов из 12 элементов. Если пропустить эти случаи, компилятор может вычесть 4 перед сравнением разницы с 8, а затем использовать таблицу из 8 элементов.

Одна из трудностей при попытке оптимизировать операторы переключения состоит в том, что компиляторы, как правило, лучше, чем программисты, знают, как производительность разных подходов будет варьироваться при заданных входных данных, но программисты могут лучше знать, чем компиляторы, какое распределение входных данных получит программа. Учитывая что-то вроде:

if (x==0)
  y++;
else switch(x)
{
  ...
}

«умный» компилятор может признать, что изменение кода на:

switch(x)
{
  case 0:
    y++;
    break;
  ...
}

может исключить сравнение во всех случаях, когда x не равен нулю , за счет вычисленного прыжка w курица x равна нулю. Если x большую часть времени не равен нулю, это была бы хорошая сделка. Однако, если x равен нулю 99,9% времени, это может быть плохой сделкой. Разные авторы компиляторов различаются по степени, в которой они будут пытаться оптимизировать конструкции, подобные первым, в последние.

56
задан Mark Amery 8 October 2014 в 09:36
поделиться

2 ответа

Решение, нет. Раздражающий и громоздкий обходной путь, да:

$stored_exc = null;
try {
    // Do stuff
} catch (Exception $exc) {
    $stored_exc = $exc;
    // Handle an error
}
// "Finally" here, clean up after yourself
if ($stored_exc) {
    throw($stored_exc);
}

Невероятно, но должно работать.

Обратите внимание на : PHP 5.5 наконец-то (кхм, извините) добавил блок finally: https://wiki.php.net/ rfc / finally (и это заняло всего несколько лет ... доступно в версии 5.5 RC почти через четыре года после того, как я опубликовал этот ответ ...)

61
ответ дан 26 November 2019 в 17:28
поделиться

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

Хорошие книги приводят аргументы против использования блоков finally для любых других целей, кроме освобождения ресурса, поскольку вы не можете быть уверены он будет выполнен, если произойдет что-то неприятное. Назвать это раздражающей дырой - преувеличение. Поверьте мне, чертовски много исключительно хорошего кода написано на языках без блока finally. :)

Смысл команды finally состоит в том, чтобы выполнить ее независимо от того, был ли блок попытки успешным или нет.

1
ответ дан 26 November 2019 в 17:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: