Когда-либо выгодно использовать 'goto' на языке, который поддерживает циклы и функции? Если так, почему?

Я попробовал много предлагаемых решений, но в итоге удалил файл и снова создал его, а Xcode был смягчен: /

194
задан chqrlie 25 December 2015 в 12:52
поделиться

18 ответов

Существует несколько причин использования "goto" оператора, о котором я знаю (некоторые уже говорили с этим):

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

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

Выходящие вложенные циклы

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

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

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

Примечание, что во всех этих примерах, gotos ограничиваются объемом единственной функции.

233
ответ дан Noctis Skytower 23 November 2019 в 05:22
поделиться

Edsger Dijkstra, программист, который имел крупные вклады на поле, был также известен критикой использования GoTo. Существует короткая статья о его аргументе на Википедия .

0
ответ дан bubbassauro 23 November 2019 в 05:22
поделиться

Проблема с 'goto' и самым важным аргументом 'goto-меньшего-количества программирования' перемещение, который, если Вы используете его слишком часто Ваш код, хотя это могло бы вести себя правильно, становится нечитабельным, неудобным в сопровождении, непоправимый и т.д. В 99,99% случаев 'goto' приводит к запутанному коду. Лично, я не могу думать ни о каком серьезном основании относительно того, почему я использовал бы 'goto'.

1
ответ дан cschol 23 November 2019 в 05:22
поделиться

В Perl, использовании маркировки к "goto" от цикла - использование "последнего" оператора, который подобен повреждению.

Это позволяет лучшее управление вложенными циклами.

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

1
ответ дан Abhinav 23 November 2019 в 05:22
поделиться

Точно также никто никогда не реализовывал оператор "COME FROM"....

2
ответ дан Ken Ray 23 November 2019 в 05:22
поделиться

Если так, почему?

C имеет, не мультивыравниваются/маркируют повреждение, и не все потоки управления может быть легко смоделирован с примитивами повторения и решения C. gotos имеют большое значение для возмещения этих дефектов.

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

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

2
ответ дан DrPizza 23 November 2019 в 05:22
поделиться

В модуле Perl Вы иногда хотите создать подпрограммы или закрытия на лету. Вещь, это, как только Вы создали подпрограмму, как пройти она. Вы могли просто назвать его, но тогда если подпрограмма использует caller() , это не будет столь полезно, как это могло быть. Это - то, где goto &subroutine изменение может быть полезным.

Вот быстрый пример:

sub AUTOLOAD{
  my($self) = @_;
  my $name = $AUTOLOAD;
  $name =~ s/.*:://;

  *{$name} = my($sub) = sub{
    # the body of the closure
  }

  goto $sub;

  # nothing after the goto will ever be executed.
}
<час>

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

sub factorial($){
  my($n,$tally) = (@_,1);

  return $tally if $n <= 1;

  $tally *= $n--;
  @_ = ($n,$tally);
  goto &factorial;
}

(В [1 119] версия 16 Perl 5, которая была бы лучше записана как [1 120] goto __SUB__; )

существует модуль, который импортирует tail модификатор и тот, который импортирует recur , если Вам не нравится использовать эту форму [1 123] goto .

use Sub::Call::Tail;
sub AUTOLOAD {
  ...
  tail &$sub( @_ );
}

use Sub::Call::Recur;
sub factorial($){
  my($n,$tally) = (@_,1);

  return $tally if $n <= 1;
  recur( $n-1, $tally * $n );
}
<час>

большинство других причин использовать goto лучше сделано с другими ключевыми словами.

Как [1 124] redo луг немного кода:

LABEL: ;
...
goto LABEL if $x;
{
  ...
  redo if $x;
}

Или идущий в last из небольшого количества кода от нескольких мест:

goto LABEL if $x;
...
goto LABEL if $y;
...
LABEL: ;
{
  last if $x;
  ...
  last if $y
  ...
}
3
ответ дан Brad Gilbert 23 November 2019 в 05:22
поделиться

Одна из причин goto плоха, помимо стиля кодирования то, что можно использовать его для создания , наложение , но не вложило циклы:

loop1:
  a
loop2:
  b
  if(cond1) goto loop1
  c
  if(cond2) goto loop2

Это создало бы причудливое, но возможно легальный поток управляющей структуры, где последовательность как (a, b, c, b, a, b, a, b...) возможна, который делает хакеров компилятора недовольными. По-видимому, существует много умных приемов оптимизации, которые полагаются на этот тип структуры, не происходящей. (Я должен проверить свою копию книги дракона...), результат этого мог бы (использующий некоторые компиляторы) быть, что другая оптимизация не сделана для кода, который содержит goto с.

могло бы быть полезно, если Вы знаете это просто, "о, между прочим", оказывается, убеждает компилятор испустить более быстрый код. Лично, я предпочел бы пытаться объяснить компилятору о том, что вероятно и что не перед использованием приема как goto, но возможно, я мог бы также попробовать goto прежде, чем взломать ассемблер.

7
ответ дан Anders Eurenius 23 November 2019 в 05:22
поделиться

Я записал больше, чем несколько строк ассемблера за эти годы. В конечном счете каждый высокоуровневый язык компилирует вниз в gotos. Хорошо, назовите их "ответвлениями" или "переходами" или безотносительно, но они - gotos. Кто-либо может записать менее ассемблерный?

Теперь уверенный, можно указать на Фортран, C или ОСНОВНОГО программиста, который для разбушеваний с gotos рецепт приготовления болоньезе спагетти. Ответ однако не должен избегать их, но использовать их тщательно.

нож А может использоваться, чтобы приготовить пищу, освободить кого-то или уничтожить кого-то. Мы обходимся без ножей через страх перед последним? Так же goto: используемый небрежно это препятствует, используемый тщательно это помогает.

12
ответ дан bugmagnet 23 November 2019 в 05:22
поделиться

#ifdef TONGUE_IN_CHEEK

Perl имеет goto, который позволяет Вам реализовывать последние вызовы плохого человека.:-P

sub factorial {
    my ($n, $acc) = (@_, 1);
    return $acc if $n < 1;
    @_ = ($n - 1, $acc * $n);
    goto &factorial;
}

#endif

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

(Тот же комментарий может относиться longjmp, исключения, call/cc , и т.п.---, они имеют законное использование, но могут легко быть оскорблены. Например, выдавая исключение просто для выхода из глубоко вложенной управляющей структуры, при абсолютно неисключительных обстоятельствах.)

14
ответ дан Chris Jester-Young 23 November 2019 в 05:22
поделиться

В переключатель C# , который позволяет оператор doest не, проваливается . Так goto используется для передачи управления определенной маркировке случая переключателя или значение по умолчанию маркировка.

, Например:

switch(value)
{
  case 0:
    Console.Writeln("In case 0");
    goto case 1;
  case 1:
    Console.Writeln("In case 1");
    goto case 2;
  case 2:
    Console.Writeln("In case 2");
    goto default;
  default:
    Console.Writeln("In default");
    break;
}

Редактирование: существует одно исключение на, "нет проваливаются" правило. Провалитесь позволяется, если оператор выбора не имеет никакого кода.

28
ответ дан Jakub Šturc 23 November 2019 в 05:22
поделиться

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

6
ответ дан Ari Pernick 23 November 2019 в 05:22
поделиться

С тех пор goto делает обоснование о процессе выполнения программы трудным <глоток> 1 (иначе. “spaghetti code”), goto вообще только используется для компенсации недостающих возможностей: использование goto может на самом деле быть приемлемым, но только если язык не предлагает более структурированный вариант для получения той же цели. Возьмите пример Сомнения:

правило с goto, что мы используем, состоит в том, что goto хорошо к для переходящего вперед к единственной точке очистки выхода в функции.

Это - истинный †“, но только если язык не позволяет структурированную обработку исключений с кодом очистки (таким как RAII или finally), который делает то же задание лучше (как это особенно создается для того, чтобы сделать его), или когда будет серьезное основание не использовать структурированную обработку исключений (но у Вас никогда не будет этого случая кроме на очень низком уровне).

На большинстве других языков, единственное приемлемое использование goto должно выйти из вложенных циклов. И даже там почти всегда лучше снять внешний цикл в собственный метод и использование return вместо этого.

, Кроме которого, goto знак, что недостаточно мысли вошло в конкретную часть кода.

<час>

<глоток> 1 Современные языки, которые поддерживают goto реализация некоторые ограничения (например, goto может не вскочить или из функций), но проблема существенно остается тем же.

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

36
ответ дан Konrad Rudolph 23 November 2019 в 05:22
поделиться

В зависимости от того, какие окна инструментов открыты, VS может пытаться или не пытаться автоматически вызвать сервер группы при запуске.

Для получения наилучших результатов попробуйте:

  1. Закройте все экземпляры visual studio
  2. Откройте пустую visual studio (без проекта/решения)
  3. Посмотрите, какие окна открыты по умолчанию, если по умолчанию открыты (и активированы) обозреватель системы управления версиями или командный обозреватель, а также любые другие окна, в которых используется команда, закройте их или переключите на фоновую вкладку.
  4. Закройте visual studio

Теперь вы должны заметить, что вы можете запустить visual studio без попытки доступа к серверу TFS.

Я знаю его только в стороне от вашей проблемы, но я надеюсь, что вы найдете это полезным!

-121--735758-

Слепое соблюдение передовых практик не является наилучшей практикой. Идея избегать операторов goto как основной формы управления потоком состоит в том, чтобы избежать создания нечитаемого кода спагетти. Если их использовать скудно в нужных местах, они иногда могут быть самым простым, ясным способом выражения идеи. Уолтер Брайт, создатель компилятора Zortech C++ и языка программирования D, использует их часто, но разумно. Даже с утверждениями goto его код все еще полностью читаем.

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

151
ответ дан 23 November 2019 в 05:22
поделиться

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

В качестве иллюстрации я приведу вам пример, который здесь еще никто не показал:

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

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

// Overwrite an element with same hash key if it exists
for (add_index=0; add_index < ELEMENTS_PER_BUCKET; add_index++)
  if (slot_p[add_index].hash_key == hash_key)
    goto add;

// Otherwise, find first empty element
for (add_index=0; add_index < ELEMENTS_PER_BUCKET; add_index++)
  if ((slot_p[add_index].type == TT_ELEMENT_EMPTY)
    goto add;

// Additional passes go here...

add:
// element is written to the hash table here

Теперь, если бы я не использовал goto, как бы выглядел этот код?

Примерно так:

// Overwrite an element with same hash key if it exists
for (add_index=0; add_index < ELEMENTS_PER_BUCKET; add_index++)
  if (slot_p[add_index].hash_key == hash_key)
    break;

if (add_index >= ELEMENTS_PER_BUCKET) {
  // Otherwise, find first empty element
  for (add_index=0; add_index < ELEMENTS_PER_BUCKET; add_index++)
    if ((slot_p[add_index].type == TT_ELEMENT_EMPTY)
      break;
  if (add_index >= ELEMENTS_PER_BUCKET)
   // Additional passes go here (nested further)...
}

// element is written to the hash table here

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

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

7
ответ дан 23 November 2019 в 05:22
поделиться

Я нахожу использование do{} while(false) совершенно отвратительным. Можно убедить меня, что это необходимо в каком-то странном случае, но никогда - что это чистый разумный код.

Если вы должны сделать такой цикл, почему бы не сделать зависимость от переменной flag явной?

for (stepfailed=0 ; ! stepfailed ; /*empty*/)
2
ответ дан 23 November 2019 в 05:22
поделиться

Все, кто выступает против goto, прямо или косвенно ссылаются на статью GoTo Considered Harmful Эдсгера Дейкстры для обоснования своей позиции. Жаль, что статья Дейкстры не имеет практически никакого отношения к тому, как операторы goto используются в наши дни, и поэтому то, что говорится в статье, практически не применимо к современной сцене программирования. Мем goto-less сейчас граничит с религией, вплоть до ее писаний, продиктованных свыше, ее первосвященников и изгнания (или еще хуже) предполагаемых еретиков.

Давайте рассмотрим статью Дейкстры в контексте, чтобы пролить немного света на эту тему.

Когда Дейкстра писал свою статью, популярными языками того времени были неструктурированные процедурные языки, такие как BASIC, FORTRAN (ранние диалекты) и различные языки ассемблера. Для людей, использующих языки более высокого уровня, было вполне обычным делом прыгать по всей своей кодовой базе в извилистых, искаженных потоках выполнения, что породило термин "код спагетти". Вы можете убедиться в этом, заглянув в классическую игру Trek, написанную Майком Мэйфилдом, и попытавшись понять, как все работает. Потратьте несколько минут, чтобы посмотреть на это.

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

Я уже слышу возвышенные песнопения культистов, когда они предстанут перед еретиком. "Но", - будут скандировать они, - "вы можете сделать код очень трудным для чтения с помощью goto в Си". Да? Код можно сделать очень трудным для чтения и без goto. Например, вот этот:

#define _ -F<00||--F-OO--;
int F=00,OO=00;main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO()
{
            _-_-_-_
       _-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
        _-_-_-_-_-_-_-_
            _-_-_-_
}

Ни одного goto в поле зрения, поэтому он должен быть легко читаемым, верно? Или как насчет этого:

a[900];     b;c;d=1     ;e=1;f;     g;h;O;      main(k,
l)char*     *l;{g=      atoi(*      ++l);       for(k=
0;k*k<      g;b=k       ++>>1)      ;for(h=     0;h*h<=
g;++h);     --h;c=(     (h+=g>h     *(h+1))     -1)>>1;
while(d     <=g){       ++O;for     (f=0;f<     O&&d<=g
;++f)a[     b<<5|c]     =d++,b+=    e;for(      f=0;f<O
&&d<=g;     ++f)a[b     <<5|c]=     d++,c+=     e;e= -e
;}for(c     =0;c<h;     ++c){       for(b=0     ;b<k;++
b){if(b     <k/2)a[     b<<5|c]     ^=a[(k      -(b+1))
<<5|c]^=    a[b<<5      |c]^=a[     (k-(b+1     ))<<5|c]
;printf(    a[b<<5|c    ]?"%-4d"    :"    "     ,a[b<<5
|c]);}      putchar(    '\n');}}    /*Mike      Laman*/

Здесь тоже нет goto. Поэтому он должен быть читабельным.

К чему я привел эти примеры? Не особенности языка делают нечитаемый, не поддерживаемый код. Не синтаксис делает это. Это происходит из-за плохих программистов. А плохие программисты, как вы можете видеть в приведенном выше примере, могут сделать любую особенность языка нечитабельной и непригодной для использования. Например, циклы for. (Вы же видите их, правда?)

Справедливости ради, некоторыми языковыми конструкциями злоупотреблять легче, чем другими. Однако, если вы программист на C, я бы более внимательно изучил около 50% случаев использования #define, прежде чем отправляться в крестовый поход против goto!

Итак, для тех, кто потрудился дочитать до конца, есть несколько ключевых моментов, которые следует отметить.

  1. Статья Дейкстры о goto операторах была написана для среды программирования, где goto был гораздо более потенциально вредным, чем в большинстве современных языков, не являющихся ассемблером.
  2. Автоматически отбрасывать все использования goto из-за этого так же рационально, как сказать: "Я пытался развлечься однажды, но мне не понравилось, так что теперь я против".
  3. В коде есть законное использование современных (анемичных) операторов goto, которые не могут быть адекватно заменить другими конструкциями.
  4. Есть, конечно, и нелегитимное использование тех же утверждений.
  5. Есть также незаконное использование современных управляющих операторов, таких как мерзость "godo", где всегда ложный do цикл разрывается с помощью break вместо goto. Это часто хуже, чем разумное использование goto.
896
ответ дан 23 November 2019 в 05:22
поделиться

Ну, есть одна вещь, которая всегда хуже, чем goto's; странное использование других операторов программного потока, чтобы избежать goto:

Примеры:

    // 1
    try{
      ...
      throw NoErrorException;
      ...
    } catch (const NoErrorException& noe){
      // This is the worst
    } 


    // 2
    do {
      ...break; 
      ...break;
    } while (false);


    // 3
    for(int i = 0;...) { 
      bool restartOuter = false;
      for (int j = 0;...) {
        if (...)
          restartOuter = true;
      if (restartOuter) {
        i = -1;
      }
    }

etc
etc
35
ответ дан 23 November 2019 в 05:22
поделиться
Другие вопросы по тегам:

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