Примеры хороших gotos на C или C++
В этой теме мы рассмотрим примеры правильного 9X_cpp использования goto
в C или C++. Он вдохновлен 9X_c++ an answer, люди проголосовали за него, потому что 9X_cxx думали, что я шучу.
Резюме (ярлык изменен 9X_cxx с оригинала, чтобы прояснить намерения):
infinite_loop: // code goes here goto infinite_loop;
Почему 9X_c++ это лучше, чем альтернативы:
- Это специфично.
goto
- это языковая конструкция, которая вызывает безусловная ветвь. Альтернативы зависят от использования структур поддерживающие условные ветви, с вырожденным всегда верным состояние. - Этикетка подтверждает намерение без лишних комментариев.
- Читателю не нужно сканировать промежуточный код для ранних
break
s (хотя все еще возможно беспринципный хакер симулироватьcontinue
с раннимgoto
).
Правила:
- Сделайте вид, что готофобы не победить. Понятно, что выше не может использоваться в реальном коде, потому что это противоречит устоявшейся идиоме.
- Предположим, что все мы слышали о 'Гото считается вредным' и знай этот goto можно использовать для записи код спагетти.
- Если вы не согласны с примером, критиковать это по техническим причинам один ('Потому что людям не нравится goto 'не является технической причиной).
Посмотрим, сможем 9X_c ли мы поговорить об этом, как взрослые.
Изменить
На 9X_cxx этом вопрос, кажется, закончен. Это дало 9X_goto несколько качественных ответов. Спасибо 9X_c++ всем, особенно те, кто серьезно относился 9X_cxx к моему примеру с петлей. Большинство скептиков 9X_cpp были обеспокоены из-за отсутствия рамки 9X_cxx блока. Как отметил @quinmars в комментарии, вы 9X_cxx всегда можете поставить фигурные скобки 9X_cxx вокруг тело петли. Попутно отмечу, что for(;;)
и 9X_cxx while(true)
не дают вам фигурных скобок бесплатно (и 9X_c их пропуск может вызвать досадные ошибки). В 9X_goto любом случае, я больше не буду тратить впустую из 9X_c ваших умственных способностей на эту пустяк 9X_goto - я могу жить с безобидными и идиоматическими 9X_cpp for(;;)
и while(true)
(с тем же успехом, если я хочу сохранить 9X_goto свою работу).
Учитывая другие ответы, я вижу, что 9X_c++ многие люди рассматривают goto
как то, что вы 9X_cpp всегда придется по другому переписать. Конечно, вы 9X_goto можете избежать goto
, введя цикл, дополнительный 9X_cxx флаг, стек вложенных if
или чего-то еще, но 9X_goto почему бы не подумать, является ли goto
возможно 9X_cpp лучший инструмент для работы? Другими словами, на 9X_c сколько уродства готовы вынести люди, чтобы 9X_c++ избежать использования встроенной языковой 9X_goto функции по прямому назначению? Я считаю, что даже 9X_c установка флага - слишком высокая цена. Мне 9X_goto нравится, когда мои переменные представляют 9X_cpp вещи в области проблемы или решения. "Исключительно, чтобы 9X_goto избежать goto
" не сокращает его.
Я приму 9X_cxx первый ответ, который дал шаблон C для перехода 9X_goto к блоку очистки. ИМО, это самый веский аргумент 9X_c++ в пользу goto
из всех опубликованных ответов, конечно если 9X_goto измерить это по искривлению, через которое 9X_c++ должен пройти ненавистник, чтобы избежать 9X_c++ этого.
- Я согласен с тем, что «goto» может быть полезным (ниже приведены отличные примеры), но я не согласен с вашим конкретным примером. Строка с надписью «goto infinite_loop» звучит так, как будто она означает «перейти к той части кода, где мы собира ...
Ответ #1
Ответ на вопрос: Примеры хороших gotos на C или C++
Вот одна уловка, которую я слышал от людей. Хотя 9X_cxx я никогда не видел его в дикой природе. И 9X_cpp это применимо только к C, потому что в C++ есть 9X_goto RAII, чтобы сделать это более идиоматично.
void foo() { if (!doA()) goto exit; if (!doB()) goto cleanupA; if (!doC()) goto cleanupB; /* everything has succeeded */ return; cleanupB: undoB(); cleanupA: undoA(); exit: return; }
- Что в этом плохого? (кроме того факта, что комментарии не понимают ...
Ответ #2
Ответ на вопрос: Примеры хороших gotos на C или C++
Классическая потребность в GOTO в C заключается 9X_c++ в следующем
for ... for ... if(breakout_condition) goto final; final:
Нет простого способа выйти из 9X_cxx вложенных циклов без перехода.
- Я определенно согласен с Дариусом - преобразовать его в функцию и ...
Ответ #3
Ответ на вопрос: Примеры хороших gotos на C или C++
Вот мой нелепый пример (от Stevens APITUE) для 9X_goto системных вызовов Unix, которые могут быть 9X_goto прерваны сигналом.
restart: if (system_call() == -1) { if (errno == EINTR) goto restart; // handle real errors }
Альтернатива - вырожденный 9X_c++ цикл. Эта версия читается как английская 9X_cxx «если системный вызов был прерван сигналом, перезапустите 9X_cxx его».
- @Amarghosh, `continue` - это прос ...
Ответ #4
Ответ на вопрос: Примеры хороших gotos на C или C++
Если устройству Даффа не требуется goto, то 9X_cpp и вам не нужно! ;)
void dsend(int count) { int n; if (!count) return; n = (count + 7) / 8; switch (count % 8) { case 0: do { puts("case 0"); case 7: puts("case 7"); case 6: puts("case 6"); case 5: puts("case 5"); case 4: puts("case 4"); case 3: puts("case 3"); case 2: puts("case 2"); case 1: puts("case 1"); } while (--n > 0); } }
приведенный выше код из 9X_goto Википедии entry.
- Я бы не стал нанимать программиста без чувства юмора.<p><span ...
Ответ #5
Ответ на вопрос: Примеры хороших gotos на C или C++
Кнут написал статью "Структурированное 9X_c++ программирование с помощью операторов GOTO", вы 9X_cpp можете получить ее, например из here. Там вы 9X_c найдете множество примеров.
- Какие предположения? Его примеры сегодня так же реальны для процедурного языка, как C (он приводит их в некотором псевдокоде), как ...
Ответ #6
Ответ на вопрос: Примеры хороших gotos на C или C++
Я не имею ничего против gotos в целом, но 9X_cxx могу придумать несколько причин, по которым 9X_cxx вы не хотели бы использовать их для цикла, как 9X_c вы упомянули:
- Он не ограничивает область действия, поэтому любые временные переменные, которые вы используете внутри, будут освобождены позже.
- Это не ограничивает объем, поэтому может привести к ошибкам.
- Это не ограничивает область видимости, поэтому вы не можете повторно использовать те же имена переменных позже в будущем коде в той же области.
- Это не ограничивает область видимости, поэтому вы можете пропустить объявление переменной.
- Люди не привыкли к этому, и это затруднит чтение вашего кода.
- Вложенные циклы этого типа могут привести к спагетти-коду, нормальные циклы не приведут к спагетти-коду.
- is inf_loop: {/ * тело ...
Ответ #7
Ответ на вопрос: Примеры хороших gotos на C или C++
Очень часто.
do_stuff(thingy) { lock(thingy); foo; if (foo failed) { status = -EFOO; goto OUT; } bar; if (bar failed) { status = -EBAR; goto OUT; } do_stuff_to(thingy); OUT: unlock(thingy); return status; }
Единственный случай, когда я 9X_goto когда-либо использовал goto
, - это переход вперед, обычно 9X_goto из блоков, а не в блоки. Это позволяет избежать 9X_c++ злоупотребления do{}while(0)
и другими конструкциями, увеличивающими 9X_c++ вложенность, при сохранении читабельного 9X_goto структурированного кода.
- Я думаю, что это типичный способ обработки ошибок C. Я не вижу, чтобы он был заменен крас ...
Ответ #8
Ответ на вопрос: Примеры хороших gotos на C или C++
Хорошее место для использования goto - процедура, которая 9X_cpp может быть прервана в нескольких точках, каждая 9X_cxx из которых требует различных уровней очистки. Gotophobes 9X_c всегда может заменить gotos на структурированный 9X_cxx код и серию тестов, но я думаю, что это 9X_cxx проще, потому что он устраняет чрезмерные 9X_c++ отступы:
if (!openDataFile()) goto quit; if (!getDataFromFile()) goto closeFileAndQuit; if (!allocateSomeResources) goto freeResourcesAndQuit; // Do more work here.... freeResourcesAndQuit: // free resources closeFileAndQuit: // close file quit: // quit!
- Если вы создали эти 3 дополнительные функции, вам нужно будет передать указатели / дескрипторы ресурсов и файлов, которые нужно освободить / закрыть. Вы, вероятно, заставили бы freeResourcesCloseFileQuit() вызвать closeFileQuit(), ко ...
Ответ #9
Ответ на вопрос: Примеры хороших gotos на C или C++
@ fizzer.myopenid.com: размещенный вами 9X_c++ фрагмент кода эквивалентен следующему:
while (system_call() == -1) { if (errno != EINTR) { // handle real errors break; } }
Я 9X_cpp определенно предпочитаю эту форму.
- Хорошо, я знаю, что операт ...
Ответ #10
Ответ на вопрос: Примеры хороших gotos на C или C++
Несмотря на то, что со временем я возненавидел 9X_c++ этот шаблон, он встроен в программирование 9X_goto COM.
#define IfFailGo(x) {hr = (x); if (FAILED(hr)) goto Error} ... HRESULT SomeMethod(IFoo* pFoo) { HRESULT hr = S_OK; IfFailGo( pFoo->PerformAction() ); IfFailGo( pFoo->SomeOtherAction() ); Error: return hr; }
Ответ #11
Ответ на вопрос: Примеры хороших gotos на C или C++
Вот пример хорошего перехода:
// No Code
9X_c
- Это не очень полезно<p><span c ...
Ответ #12
Ответ на вопрос: Примеры хороших gotos на C или C++
Я видел, как goto используется правильно, но 9X_cpp ситуации обычно безобразны. Это только тогда, когда 9X_cpp использование самого goto
намного меньше, чем 9X_cpp исходное. @Johnathon Holland проблема в 9X_cpp том, что ваша версия менее ясна. люди, кажется, боятся 9X_c локальных переменных:
void foo() { bool doAsuccess = doA(); bool doBsuccess = doAsuccess && doB(); bool doCsuccess = doBsuccess && doC(); if (!doCsuccess) { if (doBsuccess) undoB(); if (doAsuccess) undoA(); } }
И я предпочитаю такие 9X_cpp циклы, но некоторые люди предпочитают while(true)
.
for (;;) { //code goes here }
- Никогда и никогда не сравнивайте логическое значение с истиной или ложью. Это уже логическое значение; просто используйте "doBsuccess = doAsuccess && doB();" и вм ...
-
27
-
6
-
2
-
4
-
4
-
24
-
43
-
20
-
9
-
7
-
2
-
4
-
12
-
4
-
5
-
8
-
20
-
3
-
6
-
7
-
5
-
6
-
12
-
16
-
3
-
2
-
1
-
6
-
2
-
3
-
6
-
3
-
6
-
2
-
1
-
11
-
3
-
8
-
25
-
4
-
8
-
9
-
11
-
7
-
8
-
4
-
27
-
13
-
3
-
7