Являются ли операторы goto эффективными по сравнению с вызывающими функциями?

У меня есть следующий код на С++ здесь:

#include <iostream>

int main(int argc, const char * argv[])
{
    goto line2;
line1:
    std::cout << "line 1";
    goto line3;
line2:
    std::cout << "line 2";
    goto line1;
line3:
    std::cout << "line 3";
    goto line4;
line4:
    std::cout << "Hello, World!\n";
    return 0;
}

Если я сделал большую программу, скажем, из 10 000 строк кода, и решил, что никогда не буду использовать функции, которые пишу сам, я использую только операторы goto. Я использую только глобальные переменные. Я немного безумен с точки зрения лучших практик, но для очень конкретной цели. Вопрос в том, будет ли эффективно прыгать с операторами goto? Что делать, если у меня есть 1000 ярлыков goto?

Операторы goto транслируются непосредственно в машинный код, который говорит компьютеру просто ПЕРЕЙТИ на другой адрес памяти? Это более низкая стоимость машины, чтобы прыгать так, по сравнению со стоимостью вызова функции?

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


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


Чтобы прояснить вопрос, я обеспокоен в этом случае использования gotos только с программой из 10 000 строк, чтобы сравнить ее с традиционной программой, использующей функции. Есть несколько способов сравнить и сопоставить эти две программы, например, как будет работать кэш ЦП. Какую бы экономию это дало без вызовов функций. Как это повлияет на кэш ЦП без стека вызовов, поскольку кэши ЦП обычно удерживают стек закрытым. Будет ли для этого случай, когда он может иметь отрицательный удар по производительности из-за неправильного использования кеша. Какова фактическая стоимость вызова функции по сравнению с скачком с точки зрения эффективности времени. Есть много способов сравнить и противопоставить два стиля программирования с точки зрения эффективности.


person Phil    schedule 07.01.2013    source источник
comment
Пожалуйста, не пишите код таким образом. Всегда.   -  person Spudd86    schedule 08.01.2013
comment
Почему все чувствуют себя обязанными сказать мне это?... Я пишу код более 15 лет на коммерческой основе и начал программировать в 12 лет, я никогда не пишу такой код. За исключением, в данном конкретном случае, моего собственного проекта.   -  person Phil    schedule 08.01.2013
comment
Это интересно, каждый, кто увидит этот вопрос, сразу скажет: о нет, готос, это зло, но вы не подумали, что для этого есть веские причины. Я разрабатываю компьютерный язык, который компилируется в код C++ и должен использовать операторы Goto для передачи выполнения в разные части языка. Знаете ли вы, что C++ используется для компиляции кода C, а затем компилируется компилятором C? Coffeescript компилируется в Javascript и запускается как Javascript. Язык, который я разрабатываю, легче скомпилировать в C++, если я использую переходы в разные места кода.   -  person Phil    schedule 08.01.2013
comment
Пожалуйста, помните, что компьютер — это просто машина, которая выполняет инструкции, и как мы ее используем, зависит только от нас.   -  person Phil    schedule 08.01.2013
comment
Я не говорю, что gotos это зло, я говорю gotos вместо вызовов функций, это зло Я написал код, который использует gotos, вы не можете скомпилировать C++ в C с текущими версиями языка, по крайней мере, неэффективно. То, что вы предлагаете написать, - это ТОЧНО то, что побудило статью Гото считать вредной.   -  person Spudd86    schedule 08.01.2013
comment
Я сказал, что вы выходите за рамки вопроса. Не нужно говорить мне, что это плохая идея с точки зрения обслуживания, понятности кода, лучших практик И вопрос закрыт. Я не буду отвечать на дальнейшие утверждения о том, хороши или плохи goto.   -  person Phil    schedule 09.01.2013
comment
@Phil Несколько ответов ответили на ваш вопрос, не было ли какой-то информации?   -  person Seth Carnegie    schedule 09.01.2013
comment
Да. Вы хотите знать, что это такое, или вы задаете риторический вопрос?   -  person Phil    schedule 09.01.2013
comment
Вопрос закрыт. Так почему ты беспокоишься об этом?   -  person Phil    schedule 09.01.2013
comment
@ Фил, да, я хочу знать, что это такое. Я спрашиваю, потому что я написал ответ и проголосовал за повторное открытие. Кроме того, если вы не сделаете @ SethCarnegie, я не знаю, что вы ответили. И я считаю, что закрытые вопросы по-прежнему должны иметь принятый ответ, если он опубликован.   -  person Seth Carnegie    schedule 09.01.2013
comment
@SethCarnegie Прекратите приставать к людям за репутацию, вам ничего не должны и никаких вопросов, открытых или закрытых, требуется принятый ответ. Это полностью необязательно и полностью остается на усмотрение человека, разместившего вопрос.   -  person meagar    schedule 09.01.2013
comment
@meagar Нет, он может делать все, что хочет, но у меня такое чувство, что он закрыл это из-за разочарования. Заметьте, я не голосовал за закрытие. И вы понимаете, что нужно означает должно быть, иначе..., когда я просто имею в виду, что было бы хорошо, если бы это было так. У меня нет времени тебе это объяснять.   -  person Seth Carnegie    schedule 09.01.2013
comment
@SethCarnegie Я говорю, что нужно иметь в виду то, что на самом деле означает необходимость. У слов есть значения, и они довольно хорошо определены. «Нуждаться» абсолютно не означает «хорошо иметь» в любом контексте или возможном использовании этого слова.   -  person meagar    schedule 09.01.2013
comment
@SethCarnegie ... вы сказали И я считаю, что закрытые вопросы все еще должны иметь принятый ответ, если он опубликован. Потребность, используемая здесь, означает то же самое, что и Мигар. Хорошо, это сходит с ума, это закрытый вопрос в далеком захолустье интернета и даже не настоящий, и вы начинаете спорить о значении слова «Потребность». Пожалуйста, идите на урок английского, если хотите обсудить значение слов, спасибо.   -  person Phil    schedule 10.01.2013


Ответы (6)


Операторы goto транслируются непосредственно в машинный код, который говорит компьютеру просто ПЕРЕЙТИ на другой адрес памяти?

Да.

Это более низкая стоимость машины, чтобы прыгать так, по сравнению со стоимостью вызова функции?

Да.

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

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

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

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

person Seth Carnegie    schedule 07.01.2013
comment
Оптимизация — это нечто большее, чем просто предотвращение перегрузки вызовов функций. Хорошо, что вы упомянули о кеше ЦП. - person Krishnabhadra; 07.01.2013
comment
@Krishnabhadra, да, я не имел в виду, что это все, что может сделать компилятор. Я сделаю заметку об этом. - person Seth Carnegie; 07.01.2013
comment
Мне категорически не нравятся ответы на вопросы об оптимизации, в которых говорится, что компилятор умнее вас. Сейчас это может быть правдой, но не нужно много усилий, чтобы сделать это ложью. По большей части компиляторы далеко не умны; они просто быстрые и настойчивые. Второй абзац о размере кода также вводит в заблуждение; компиляторы на самом деле находятся в невыгодном положении по сравнению с компетентным программистом с высоким уровнем знания кода. Но, хотя я не согласен с большей частью ответа, фундаментальный момент, заключающийся в том, что встраивание в основном выполняется для функций, верен. - person Veedrac; 09.04.2017

Операторы goto транслируются непосредственно в машинный код, который говорит компьютеру просто ПЕРЕЙТИ на другой адрес памяти?

Довольно много.

Это более низкая стоимость машины, чтобы прыгать так, по сравнению со стоимостью вызова функции?

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

я немного сумасшедший

Да.

person James    schedule 07.01.2013

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

И да поможет вам Бог, когда с этим кодом что-то не работает. Или когда кто-то другой должен его поддерживать.

person DWright    schedule 07.01.2013
comment
Или когда кто-то другой должен поддерживать его.. Ой.. - person Krishnabhadra; 07.01.2013
comment
Это грубое упрощение. Компиляторы делают то, что называется оптимизацией. Я бы поставил на то, что компилятор создаст более оптимальный код при использовании функций, а не 10 000 строк кода, содержащих 1000 переходов. - person meagar; 07.01.2013
comment
Да, скудный, ваш комментарий - это ответ на вопрос, тем более что оптимизация производительности очень заботит ОП... - person Krishnabhadra; 07.01.2013
comment
Если вы еще раз посмотрите на то, что я сказал, вы увидите, что я старался быть осторожным и не слишком упрощать то, чего оптимизатор достигнет или не достигнет. - person DWright; 07.01.2013
comment
@кришнабхадра. Как только это станет нетривиальным фрагментом кода, он, вероятно, будет минимально быстрее, чем с вызовами функций. В нетривиальном фрагменте кода будет задействовано достаточно переменных, поэтому компилятор не будет оптимизировать или встраивать все вызовы функций. В результате стек будет время от времени толкаться или извлекаться. это не будет быстрее. Это не значит, что gotos лучше. На самом деле, верно обратное. - person DWright; 07.01.2013
comment
+1 В комментариях много людей, которые, похоже, ничего не знают об оптимизации кода или о том, как компиляторы обрабатывают gotos. - person Jim Balter; 07.01.2013

1) Вопрос в том, будет ли эффективно перескакивать с операторами goto? Что делать, если у меня 1000 ярлыков перехода?

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

2) Переводятся ли операторы goto непосредственно в машинный код, который говорит компьютеру просто ПЕРЕЙТИ на другой адрес памяти?

ДА (как правильно указали другие)

3) Меньше ли стоимость таких прыжков в машине по сравнению со стоимостью вызова функции?

ДА, только если ваш компилятор доисторический и не имеет встроенного механизма оптимизации. В противном случае НЕТ.

И я не говорю о лучших практиках.

person Krishnabhadra    schedule 07.01.2013
comment
Пожалуйста, рассмотрите 1000 операторов goto в 10 000 строк кода. - person Phil; 07.01.2013
comment
@Phil снова (как скудный указал в своем комментарии), никто не может ответить на этот вопрос 1) не видя вашего 10 000-строчного кода (но я не хочу его видеть) 2) знаю о компиляторе/машине, на которой вы запускаете этот 3) компилятор оптимизации, которые вы включаете/отключаете. Мы можем только сказать следующее: в обычном случае с современными компиляторами программисту не нужно сильно беспокоиться о накладных расходах в механизмах вызова функций. Опять же, это зависит от компилятора. - person Krishnabhadra; 07.01.2013

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

Оператор goto эквивалентен инструкции безусловного перехода (например, jmp). Область действия goto будет внутри файла.

Ричи предлагает избегать использования оператора goto, и если вы все еще хотите/должны использовать оператор goto, используйте его в подходе «сверху вниз». Не используйте его в подходе «снизу вверх».

Ну, это детали учебника.

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

Существует множество других средств, таких как циклы, условные операторы, операторы break и continue, функции и т. д., которые помогут вам избежать таких проблем.

Надеюсь, поможет.....

person Kinjal Patel    schedule 07.01.2013
comment
запрос ----> Переводят ли операторы goto непосредственно в машинный код, который говорит компьютеру просто ПЕРЕЙТИ на другой адрес памяти? оператор repy ----› goto эквивалентен инструкции безусловного перехода (например, jmp ). Область действия goto будет внутри файла. - person Kinjal Patel; 07.01.2013
comment
запрос ------ › Вопрос в том, будет ли эффективно прыгать с операторами goto? Что делать, если у меня есть 1000 ярлыков goto? ответ ------- › Практически вы должны быть очень уверены, где использовать оператор goto и после перехода goto, где будет поток вашей программы, иначе, как вы упомянули с 1000 операторами goto, вам также будет трудно решить поток программы, забудьте о других. Так что дальнейшее совершенствование вашей программы будет очень-очень сложным. - person Kinjal Patel; 07.01.2013

Короче говоря, операторы GoTo могут быть эффективными, но именно так они и используются. По словам Герберта Шильдта (C++ с нуля), «нет ситуаций программирования, требующих использования оператора goto — это не элемент, необходимый для завершения языка». В конечном счете, основная причина, по которой многие программисты не любят этот оператор, заключается в том, что операторы goto имеют тенденцию загромождать ваш код и/или затруднять его чтение, поскольку, как следует из названия, операторы goto могут перескакивать с места на место. С учетом сказанного, бывают случаи, когда оператор goto может уменьшить беспорядок, а также сделать код более эффективным, но это полностью зависит от того, как вы их используете, и от контекста, в котором они используются. Лично я бы рекомендовал использовать вызовы функций. , в отличие от нескольких операторов goto; другие могут не согласиться.

person David Venegoni    schedule 07.01.2013
comment
Спасибо, вежливо - я знаю это. Я не пытаюсь начать дискуссию между вызовами goto и функций. - person Phil; 07.01.2013
comment
Лол, да, я немного поздно увидел твою последнюю строчку, приношу свои извинения. - person David Venegoni; 07.01.2013