Я смотрел на некоторый код человеком и заметил, что у него, кажется, есть шаблон в его функциях:
<return-type> function(<params>)
{
<initialization>
do
{
<main code for function>
}
while(false);
<tidy-up & return>
}
Это не является плохим, более странным (фактический код довольно аккуратен и неудивителен). Это не что-то, что я видел прежде, и я задался вопросом, может ли кто-либо думать о какой-либо логике позади него - знания в другом языке, возможно?
Вы можете разбить
из сделать {...} while (false)
.
Попробуйте использовать атрибуты checkingaccount
и saving saccount
. Тот, кто это, не взорвется.
Я установил 2010, а 2008 уже установлен. У меня были тонны повешений, крушений и общих неисправностей. Переустановка 2008 не помогла, пока я не удалил все следы 2010 года из реестра.
-121--2666440- Многие уже заявили о сходстве между этой конструкцией и goto
и выразили предпочтение goto. Возможно, происхождение этого человека включало среду, где goto "ы были строго запрещены руководящими принципами кодирования?
Я работаю с Adobe InDesign SDK, и в примерах InDesign SDK почти все функции написаны таким образом. Это связано с тем, что функции обычно очень длинные. Где вам нужно выполнить QueryInterface (...), чтобы получить что-либо из объектной модели приложения. Таким образом, обычно за каждым QueryInterface следует , если
не прошел успешно, остановитесь.
Я согласен с большинством авторов об использовании в качестве тонко замаскированного goto. Макросы также упоминались как потенциальная мотивация для написания кода в этом стиле.
Я также видел, как эта конструкция использовалась в смешанных средах C / C ++ как исключение для бедняков. «Do {} while (false)» с «break» можно использовать для перехода к концу блока кода, если в цикле встречается что-то, что обычно требует исключения.
Я также отправил эту конструкцию, используемую в магазинах, где применяется идеология «единого возврата на функцию». Опять же, это вместо явного «goto» - но мотивация состоит в том, чтобы избежать множественных точек возврата, а не «пропустить» код и продолжить фактическое выполнение внутри этой функции.
Это просто: очевидно, вы можете выйти из ложного цикла в любой момент, используя оператор break
. Кроме того, блок do
является отдельной областью (что также может быть достигнуто только с помощью {...}
).
В такой ситуации, возможно, было бы лучше использовать RAII (объекты автоматически разрушаются правильно, когда функция завершается). Другой похожей конструкцией является использование goto
- да, я знаю, что это зло , но его можно использовать для создания общего кода очистки, например:
<return-type> function(<params>)
{
<initialization>
<main code for function using "goto error;" if something goes wrong>
<tidy-up in success case & return>
error:
<commmon tidy-up actions for error case & return error code or throw exception>
}
(В стороне: Конструкция do-while-false используется в Lua для поиска отсутствующего оператора continue
.)
Сколько лет было автору?
Я спрашиваю, потому что однажды в конце 80-х я наткнулся на какой-то код на Фортране, который делал это в реальном времени. Оказывается, это действительно хороший способ имитировать потоки в ОС, в которой их нет. Вы просто помещаете всю программу (ваш планировщик) в цикл и вызываете свои «подпрограммы потоков» одну за другой. Сами подпрограммы потоков представляют собой циклы, которые повторяются до тех пор, пока не произойдет одно из ряда условий (часто одно из которых время прошло). Это «кооперативная многозадачность», в которой каждый поток должен время от времени отказываться от ЦП, чтобы другие не истощались. Вы можете вложить циклические вызовы подпрограммы для имитации приоритета потока диапазоны.
В дополнение к уже упомянутым примерам «goto» в определении макроса иногда используется идиома do ... while (0), чтобы обеспечить скобки в определении и при этом заставить компилятор работать с добавлением точки с запятой в конец вызова макроса.
Это забавно. Вероятно, внутри цикла есть разрывы, как говорили другие. Я бы сделал это так:
while(true)
{
<main code for function>
break; // at the end.
}
Я думаю, это сделано для использования операторов break
или continue
. Что-то вроде логики кода "goto".
Выглядит как программист на C. В C ++ автоматические переменные имеют деструкторы, которые вы используете для очистки, поэтому не нужно ничего убирать перед возвратом. В C у вас не было этой идиомы RAII , поэтому, если у вас есть общий код очистки, вы либо goto
, либо используйте сквозной цикл, как указано выше.
Его главный недостаток по сравнению с идиомой C ++ заключается в том, что он не приводит в порядок, если в теле возникает исключение. В C не было исключений, так что это не было проблемой, но это стало плохой привычкой в C ++.
Это очень распространенная практика. В C . Я пытаюсь думать об этом так, как будто вы хотите солгать себе способом: «Я не использую goto
». Если подумать, нет ничего плохого в аналогичном использовании goto
. Фактически это также уменьшило бы уровень отступа.
Тем не менее, я заметил, что очень часто петли do .. while
имеют тенденцию к росту. А затем они получают внутри if
и else
, что делает код не очень читабельным, не говоря уже о тестируемом.
Те делают .. пока
обычно предназначены для очистки . Во что бы то ни стало, я бы предпочел использовать RAII и вернуть ранний из функции short . С другой стороны, C не предоставляет вам столько удобства, как C ++ , что делает do .. while
одним из лучших подходов для создания уборка.
Это просто извращение , а
, чтобы получить семантику goto-tidy-up
без использования слова goto.
Это плохой тон, потому что, когда вы используете другие циклы внутри внешнего , а
разрывы
становятся неоднозначными для читателя. «Это должно идти к выходу? Или это предназначено только для выхода из внутреннего цикла?»
Используется этот трюк программистами, которые слишком стесняются использовать явный goto
в своем коде. Автор приведенного выше кода хотел иметь возможность сразу перейти к точке «очистить и вернуть» из середины кода. Но они не хотели использовать метку и явный goto
. Вместо этого они могут использовать разрыв
внутри тела вышеуказанного «ложного» цикла для достижения того же эффекта.
Я видел, что он используется как полезный шаблон, когда существует много потенциальных точек выхода для функции, но всегда требуется один и тот же код очистки, независимо от того, как функция завершается.
Это может сделать утомительное дерево if / else-if намного более легким для чтения, просто имея необходимость прерывать работу всякий раз, когда достигается точка выхода, а остальная часть логики вставляется позже.
Этот шаблон также полезен для языков, в которых нет оператора goto. Возможно, именно здесь первоначальный программист усвоил шаблон.
Возможно, он используется для того, чтобы break
можно было использовать внутри, чтобы прервать выполнение следующего кода в любой момент:
do {
if (!condition1) break;
some_code;
if (!condition2) break;
some_further_code;
// …
} while(false);
Прерывание как goto, вероятно, является ответом, но я предложу еще одну идею.
Возможно, он хотел иметь локально определенные переменные и использовал эту конструкцию для получения новой области видимости.
Помните, что хотя последний C ++ допускает {...}
где угодно, это не всегда так.
Многие отмечают, что его часто используют вместе с break как неудобный способ написания "goto". Возможно, это верно, если он написан непосредственно в функции.
В макросе, напротив, do { something; } while (false)
- это удобный способ ЗАПРЕТИТЬ точку с запятой после вызова макроса, при этом абсолютно никакая другая лексема не должна следовать за ней.
Другая возможность заключается в том, что там либо когда-то был цикл, либо итерацию предполагается добавить в будущем (например, при разработке на основе тестирования итерация не нужна для прохождения тестов, но логически было бы логично сделать там цикл, если бы функция должна была быть несколько более общей, чем требуется сейчас)
. Да, взгляните на pg _ dump
и pg _ restore
http://www.postgresql.org/docs/current/static/app-pgdump.html
http://www.postgresql.org/docs/current/static/app-pgrestore.html
-121--4903683-Кроме того, многие другие уже рассказали вам о том, как реализуется детерминированная быстрая сортировка и недетерминированная, Я считаю один, гораздо более важный аспект такого рода, это то, что при детерминированной быстрой последовательности всегда существует одинаковый порядок записей при столкновении ключей, в то время как при недетерминированных быстрых сортировках порядок таких записей может быть различным при каждом запуске сортировки.
Я думаю, вы не должны использовать недетерминированную быструю сортировку, когда у вас есть неуникальные ключи.
-121--2913789- Я видел такой код, чтобы вы могли использовать break
в качестве goto
сортов.
Это надуманный способ имитировать GOTO
, так как эти два практически идентичны:
// NOTE: This is discouraged!
do {
if (someCondition) break;
// some code be here
} while (false);
// more code be here
и:
// NOTE: This is discouraged, too!
if (someCondition) goto marker;
// some code be here
marker:
// more code be here
С другой стороны, оба эти действия действительно должны выполняться с помощью if
s:
if (!someCondition) {
// some code be here
}
// more code be here
Хотя вложенность может стать немного уродливой, если вы просто превратите длинную строку forward-GOTO
s во вложенные if
s. Однако настоящий ответ - это правильный рефакторинг, а не подражание архаичным языковым конструкциям.
Если бы вы отчаянно пытались транслитерировать алгоритм с GOTO
в нем, вы, вероятно, смогли бы сделать это с помощью этой идиомы. Хотя это, конечно, нестандартно и является хорошим индикатором того, что вы не придерживаетесь ожидаемых идиом языка.
На самом деле, я не знаю ни одного Си-подобного языка, где do/while было бы идиоматическим решением для чего-либо.
Вы, вероятно, могли бы рефакторизовать весь этот беспорядок во что-то более разумное, чтобы сделать его более идиоматичным и гораздо более читабельным.
Другая причина, о которой я могу думать, это то, что он украшает фигурные скобки, тогда как я верить в новый стандарт C ++, голые фигурные скобки недопустимы (ISO C их не любит). Иначе заглушить статический анализатор вроде пуха.
Не уверен, зачем они вам нужны, возможно, переменная область видимости или преимущество отладчика.
См. Тривиальный цикл Do While и Скобки хороши из C2.
Чтобы прояснить мою терминологию (которая, как мне кажется, следует стандартному использованию):
Открытые фигурные скобки :
init();
...
{
c = NULL;
mkwidget(&c);
finishwidget(&c);
}
shutdown();
Пустые фигурные скобки (NOP):
{}
например.
while (1)
{} /* Do nothing, endless loop */
Блок :
if (finished)
{
closewindows(&windows);
freememory(&cache);
}
, который станет
if (finished)
closewindows(&windows);
freememory(&cache);
, если скобки будут удалены, тем самым изменяя поток выполнения, а не только область локальных переменных. Таким образом, не «отдельно стоящий» или «голый».
Открытые фигурные скобки или блок могут использоваться для обозначения любого раздела кода, который может быть потенциальным для (встроенной) функции, которую вы хотите отметить, но не рефакторинг в это время.