Вопрос

goto почти повсеместно обескуражен. Стоит ли использовать это утверждение?

Это было полезно?

Решение

Это обсуждалось несколько раз на переполнении стека, и Крис Гиллум суммировал возможное использование goto:

Чисто выходить из функции

Часто в функции вы можете выделить ресурсы и вам нужно выйти в нескольких местах. Программисты могут упростить свой код, поместив код очистки ресурсов в конце функции, все «точки выхода» функции заставят этикетку очистки. Таким образом, вам не нужно писать код очистки в каждой «точке выхода» функции.

Выход из вложенных петлей

Если вы находитесь в вложенной петле и вам нужно вырваться из все Петли, готе, может сделать это намного чище и проще, чем операторы разрыва, и если проверить.

Улучшения производительности низкого уровня

Это действительно только в перф-критическом коде, но операторы GOTO очень быстро выполняются и могут дать вам повышение при прохождении функции. Однако это обоюдоострый меч, потому что компилятор обычно не может оптимизировать код, который содержит GotoS.

Я бы сказал, как многие другие утверждают, что во всех этих случаях использование goto используется в качестве средства, чтобы выйти из угла, в котором можно кодировать себя, и, как правило, является симптомом кода, который может быть рефактор.

Другие советы

Конструкции управления более высокого уровня, как правило, соответствуют понятиям в проблемной области. If/else - это решение, основанное на каком -то состоянии. В цикле говорится, чтобы выполнить какое -то действие неоднократно. Даже в заявлении перерыва говорится: «Мы делали это неоднократно, но теперь нам нужно остановиться».

С другой стороны, утверждение GOTO, как правило, соответствует концепции в программе работы, а не в проблемном домене. Он говорит, чтобы продолжить исполнение в указанной точке в программе. Анкет Кто -то читает код вывод Что это означает в отношении проблемной области.

Конечно, все конструкции более высокого уровня могут быть определены с точки зрения GOTO и простых условных ветвей. Это не значит, что они просто замаскированы. Думать о них как ограниченный Gotos - и это ограничения, которые делают их полезными. Заявление о перерыве осуществляется как прыжок к концу петли, но лучше думать о том, чтобы работать на цикле в целом.

При прочих равных, код, структура которой отражает структуру проблемы с доменом, имеет тенденцию читать и поддерживать.

Нет случаев, когда заявление о Goto абсолютно требуется (есть теорема Для этого), но есть случаи, когда это может быть наименее плохое решение. Эти случаи варьируются от языка к языку, в зависимости от того, какие конструкции более высокого уровня поддерживает язык.

Например, в C, я считаю, что есть три основных сценария, в которых подходит Goto.

  1. Вырвавшись из вложенной петли. Это было бы ненужно, если бы на языке было отмеченное заявление о перерыве.
  2. Выполнение от участка кода (как правило, корпус функции) в случае ошибки или другого неожиданного события. Это было бы ненужно, если бы у языка были исключения.
  3. Внедрение явного конечного состояния машины. В этом случае (и, я думаю, только в этом случае) goto непосредственно соответствует концепции в проблемной домене, переходя из одного состояния в указанное другое состояние, где текущее состояние представлено, с помощью которого в настоящее время выполняется блок кода Анкет

С другой стороны, явная машина конечного состояния также может быть реализована с оператором переключателя внутри цикла. Это имеет преимущество, которое каждое состояние начинается в одном и том же месте в коде, что может быть полезно для отладки, например.

Основное использование GOTO на достаточно современном языке (тот, который поддерживает, если/else и петли) состоит в том, чтобы имитировать конструкцию потока управления, которая отсутствует на языке.

Конечно, это зависит от языка программирования. Главная причина goto Был спорным из -за его вредных последствий, которые возникают, когда компилятор позволяет вам использовать его слишком либерально. Проблемы могут возникнуть, например, если это позволяет вам использовать goto Таким образом, теперь вы можете получить доступ к неонициализированной переменной или, что еще хуже, перейти к другому методу и возиться со стеком вызовов. Компилятор должен быть обязанностью запретить бессмысленному потоку управления.

Java попыталась «решить» эту проблему, не допустившись goto полностью. Тем не менее, Java позволяет вам использовать return внутри а finally блокируйте и, таким образом, вызывает исключение непреднамеренно поглощено. Та же проблема все еще существует: компилятор не выполняет свою работу. Удаление goto Из языка это не исправило.

В C#, goto так же безопасно, как break, continue, try/catch/finally а также return. Анкет Это не позволяет вам использовать неонициализированные переменные, не позволяет вам выпрыгнуть из блока, наконец, и т. Д. Компилятор будет жаловаться. Это потому, что решает настоящий Проблема, которая, как я сказал, бессмысленный поток контроля. goto Магически не отменяет анализа определенного согласия и другие разумные проверки компилятора.

Да. Когда ваши петли вложены в несколько уровней глубоко, goto это Только способ элегантного выхода из внутренней петли. Другой вариант - установить флаг и вырваться из каждой петли, если этот флаг удовлетворяет условию. Это действительно уродливо и склонен к ошибкам. В этих случаях, goto просто лучше.

Конечно, Java помечен break Заявление делает то же самое, но, не позволяя вам прыгать в произвольную точку в коде, которая аккуратно решает проблему, не позволяя сделать вещи, которые производят goto зло.

Большая часть разочарования приходит со стороны своего рода «религии», которая была создана Богом Бога Джикстра, которая была убедительной в начале 60 -х годов о своей неизбирательной власти:

  • Прыгайте куда угодно в любой блок кода
    • функция не выполнена с начала
    • петли не выполнены с самого начала
    • пропущенная инициализация переменной
  • Отпрыгните от любого блока кода без какой -либо возможной очистки.

Это больше не имеет ничего общего с goto Заявление современных языков, существование которого связано с тем, чтобы поддержать создание кодовых структур, кроме полученных языков.

В частности, первый основной момент выше разрешено, а второй очищается (если вы goto Из блока стек неразреженный должным образом, и все правильные деструкторы) называются)

Вы можете обратиться этот ответ Чтобы иметь представление о том, как даже код, не использующий GOTO, может быть нечитаемым. Проблема не само по себе, а плохое использование.

Я могу написать всю программу без использования if, просто forАнкет Конечно, это не будет хорошо читаемо, выглядит неуклюже и излишне сложным.

Но проблема не for. Анкет Это я.

Вещи как break, continue, throw, bool needed=true; while(needed) {...}, и т. д. отмечают больше, чем маскарад goto Чтобы сбежать от ссорец диджикстрарных фанатиков, через 40 лет после изобретения современных лагуж - все еще хотят их заключенных. Они забыли, о чем говорил Джикстра, они помнят только название его записки (Гото считал вредным, и это было даже не его название ONW: это было изменено редактором) и обвинить и избить, избить и обвинять каждый контракт, имея эти 4 буква размещена в последовательности.

Это 2011: пришло время понять, что goto есть отметить, чтобы справиться с GOTO Заявление Джикстра был убедительным.

Странная гостика здесь или там, если он локален для функции, редко существенно наносит ущерб читабельности. Это часто приносит пользу, привлекая внимание к тому факту, что в этом коде есть что -то необычное, что требует использования несколько необычной структуры управления.

Если (локальные) GotoS значительно наносят ущерб читабельности, то обычно это признак того, что функция, содержащая Goto, стала слишком сложной.

Последнее, что я положил в кусок C кода C, состояла в том, чтобы построить пару переплетенных петлей. Это не вписывается в нормальное определение «приемлемого» использования GOTO, но в результате функция оказалась значительно меньше и яснее. Чтобы избежать того, чтобы GOTO потребовало бы особенно грязного нарушения сухой.

Я думаю, что вся эта проблема была случаем лая неверного дерева.

Как таковой не кажется мне проблематичным, а скорее это очень часто симптом реального греха: кода спагетти.

Если GOTO вызывает серьезную пересечение линий управления потоком, то это плохо, точка. Если он не пересекает линии управления потоком, это безвредно. В серой зоне, между ними, у нас есть такие вещи, как спасение петли, есть все еще некоторые языки, которые не добавляли конструкции, которые охватывают все законные серые дела.

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

Да, GOTO может быть использован, чтобы принести пользу опыту разработчика:http://adamjonrichardson.com/2012/02/06/long-live-the-goto-statement/

Однако, как и в случае с любым мощным инструментом (указатели, множественное наследство и т. Д.), С помощью его следует дисциплинировать. Пример, приведенный в ссылке, использует PHP, который ограничивает использование конструкции GOTO в той же функции/методе и отключает возможность прыгать в новый блок управления (например, цикл, оператор переключения и т. Д.)

Зависит от языка. Например, он все еще широко используется в программировании COBOL. Я также работал над устройством Barionet 50, чей язык программирования прошивки является ранним базовым диалектом, который, конечно, требует от вас использовать GOTO.

Я бы сказал нет. Если вы найдете необходимость использования GOTO, держу пари, что есть необходимость в перепроектировании кода.

goto может быть полезен при переносе кода устаревшего ассемблера в C. В первую очередь преобразование обучения в C-инструктике в C, используя goto в качестве замены для ассемблера branch Инструкция может включить очень быструю портирование.

Я бы спорил нет. Их всегда следует заменять инструментом, более конкретным для проблемы, которую GOTO используется для решения (если только он недоступен на вашем языке). Например, операторы и исключения разрывы решают ранее выдвинутые проблемы с выключением цикла и обработку ошибок.

Лицензировано под: CC-BY-SA с атрибуция
scroll top