Я попробовал много предлагаемых решений, но в итоге удалил файл и снова создал его, а Xcode был смягчен: /
Существует несколько причин использования "goto" оператора, о котором я знаю (некоторые уже говорили с этим):
Чисто выход из функции
Часто в функции, можно выделить ресурсы и потребность выйти в нескольких местах. Программисты могут упростить свой код путем помещения кода очистки ресурса в конце функции, и все "точки выхода" функции были бы goto маркировка очистки. Таким образом, Вы не должны писать код очистки в каждой "точке выхода" функции.
Выходящие вложенные циклы
, Если Вы находитесь во вложенном цикле и должны убежать весь циклы, goto может сделать этот намного более чистый и более простой, чем операторы завершения и если-проверки.
повышения производительности Низкого уровня
Это только допустимо в критическом по отношению к перфекту коде, но операторы перехода выполняются очень быстро и могут стимулировать Вас при перемещении через функцию. Это - обоюдоострый меч, однако, потому что компилятор обычно не может оптимизировать код, который содержит gotos.
Примечание, что во всех этих примерах, gotos ограничиваются объемом единственной функции.
Edsger Dijkstra, программист, который имел крупные вклады на поле, был также известен критикой использования GoTo. Существует короткая статья о его аргументе на Википедия .
Проблема с 'goto' и самым важным аргументом 'goto-меньшего-количества программирования' перемещение, который, если Вы используете его слишком часто Ваш код, хотя это могло бы вести себя правильно, становится нечитабельным, неудобным в сопровождении, непоправимый и т.д. В 99,99% случаев 'goto' приводит к запутанному коду. Лично, я не могу думать ни о каком серьезном основании относительно того, почему я использовал бы 'goto'.
В Perl, использовании маркировки к "goto" от цикла - использование "последнего" оператора, который подобен повреждению.
Это позволяет лучшее управление вложенными циклами.
традиционный goto маркирует , поддерживается также, но я не уверен, что существует слишком много экземпляров, где это - единственный способ достигнуть того, что Вы хотите - подпрограммы и циклы должны быть достаточными для большинства случаев.
Точно также никто никогда не реализовывал оператор "COME FROM"....
Если так, почему?
C имеет, не мультивыравниваются/маркируют повреждение, и не все потоки управления может быть легко смоделирован с примитивами повторения и решения C. gotos имеют большое значение для возмещения этих дефектов.
Иногда это более ясно использовать переменную флага некоторого вида для осуществления своего рода псевдомногоуровневого повреждения, но это не всегда выше goto (по крайней мере, goto позволяет тому легко определять, куда управление переходит в, в отличие от переменной флага), и иногда Вы просто не хотите платить цену производительности искривлений флагов/других для предотвращения goto.
libavcodec является чувствительной к производительности частью кода. Прямое выражение потока управления является, вероятно, приоритетом, потому что это будет иметь тенденцию работать лучше.
В модуле 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
...
}
Одна из причин 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
прежде, чем взломать ассемблер.
Я записал больше, чем несколько строк ассемблера за эти годы. В конечном счете каждый высокоуровневый язык компилирует вниз в gotos. Хорошо, назовите их "ответвлениями" или "переходами" или безотносительно, но они - gotos. Кто-либо может записать менее ассемблерный?
Теперь уверенный, можно указать на Фортран, C или ОСНОВНОГО программиста, который для разбушеваний с gotos рецепт приготовления болоньезе спагетти. Ответ однако не должен избегать их, но использовать их тщательно.
нож А может использоваться, чтобы приготовить пищу, освободить кого-то или уничтожить кого-то. Мы обходимся без ножей через страх перед последним? Так же goto: используемый небрежно это препятствует, используемый тщательно это помогает.
#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
, и т.п.---, они имеют законное использование, но могут легко быть оскорблены. Например, выдавая исключение просто для выхода из глубоко вложенной управляющей структуры, при абсолютно неисключительных обстоятельствах.)
В переключатель 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;
}
Редактирование: существует одно исключение на, "нет проваливаются" правило. Провалитесь позволяется, если оператор выбора не имеет никакого кода.
Правило с goto, что мы используем, состоит в том, что goto хорошо к для переходящего вперед к единственной точке очистки выхода в функции. В действительно комплексных функциях мы ослабляем то правило позволить другой переход вперед. В обоих случаях мы избегаем глубоко вложенный, если операторы, которые часто происходят при проверке кода ошибки, которая помогает удобочитаемости и maintance.
С тех пор goto
делает обоснование о процессе выполнения программы трудным <глоток> 1 глоток> (иначе. “spaghetti code”), goto
вообще только используется для компенсации недостающих возможностей: использование goto
может на самом деле быть приемлемым, но только если язык не предлагает более структурированный вариант для получения той же цели. Возьмите пример Сомнения:
правило с goto, что мы используем, состоит в том, что goto хорошо к для переходящего вперед к единственной точке очистки выхода в функции.
Это - истинный †“, но только если язык не позволяет структурированную обработку исключений с кодом очистки (таким как RAII или finally
), который делает то же задание лучше (как это особенно создается для того, чтобы сделать его), или когда будет серьезное основание не использовать структурированную обработку исключений (но у Вас никогда не будет этого случая кроме на очень низком уровне).
На большинстве других языков, единственное приемлемое использование goto
должно выйти из вложенных циклов. И даже там почти всегда лучше снять внешний цикл в собственный метод и использование return
вместо этого.
, Кроме которого, goto
знак, что недостаточно мысли вошло в конкретную часть кода.
<глоток> 1 глоток> Современные языки, которые поддерживают goto
реализация некоторые ограничения (например, goto
может не вскочить или из функций), но проблема существенно остается тем же.
Кстати, то же, конечно, также верно для других функций языка, прежде всего исключения. И там существуют обычно строгие правила только использовать эти функции, где обозначено, такие как правило не использовать исключения для управления неисключительным процессом выполнения программы.
В зависимости от того, какие окна инструментов открыты, VS может пытаться или не пытаться автоматически вызвать сервер группы при запуске.
Для получения наилучших результатов попробуйте:
Теперь вы должны заметить, что вы можете запустить visual studio без попытки доступа к серверу TFS.
Я знаю его только в стороне от вашей проблемы, но я надеюсь, что вы найдете это полезным!
-121--735758- Слепое соблюдение передовых практик не является наилучшей практикой. Идея избегать операторов goto
как основной формы управления потоком состоит в том, чтобы избежать создания нечитаемого кода спагетти. Если их использовать скудно в нужных местах, они иногда могут быть самым простым, ясным способом выражения идеи. Уолтер Брайт, создатель компилятора Zortech C++ и языка программирования D, использует их часто, но разумно. Даже с утверждениями goto
его код все еще полностью читаем.
Итог: Избегать goto
ради goto
бессмысленно. Чего вы действительно хотите избежать, так это создания нечитаемого кода. Если загруженный код goto
доступен для чтения, то в этом нет ничего плохого.
Мне смешно, что некоторые люди доходят до списка случаев, когда 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 полезно, игнорируя любые хорошие. что вы не могли придумать.
Я нахожу использование do{} while(false) совершенно отвратительным. Можно убедить меня, что это необходимо в каком-то странном случае, но никогда - что это чистый разумный код.
Если вы должны сделать такой цикл, почему бы не сделать зависимость от переменной flag явной?
for (stepfailed=0 ; ! stepfailed ; /*empty*/)
Все, кто выступает против 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
!
Итак, для тех, кто потрудился дочитать до конца, есть несколько ключевых моментов, которые следует отметить.
goto
операторах была написана для среды программирования, где goto
был гораздо
более потенциально вредным, чем в большинстве современных языков, не являющихся ассемблером. goto
из-за этого так же рационально, как сказать: "Я пытался
развлечься однажды, но мне не понравилось, так что теперь я против". goto
, которые не могут быть адекватно
заменить другими конструкциями. godo
", где всегда ложный do
цикл разрывается с помощью break
вместо goto
. Это часто хуже, чем разумное использование goto
. Ну, есть одна вещь, которая всегда хуже, чем 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