Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Религиозные войны > Goto


Автор: Medved 23.12.2004, 15:26
Есть ли в этом мире ситуация, когда использование Goto актуально? Можно конечно обойтись без него, и я не помню когда в последний раз его использовал, но наверняка мне думется есть случай, когда решить задачу с помощью этого оператора - наиболее оптимальный выход?
И еще почему даже в таких современных полностью ОО языках, как Java или C# он оставлен?

Автор: bel_nikita 23.12.2004, 15:39
А потому, что без Goto - нельзя выжить и прожить в современных условиях smile

Автор: Sun 23.12.2004, 15:44
Так вроде здесь уже все области примения обсудили
http://forum.vingrad.ru/index.php?showtopic=31210

Автор: GoodBoy 23.12.2004, 15:57
Цитата(Pegas @ 23.12.2004, 15:26)
Есть ли в этом мире ситуация, когда использование Goto актуально?

С тех пор, как я перестал писать на Бейсике (лет 10 назад) у меня такой ситуации не было...
:-))))))))))))))

Автор: sergejzr 23.12.2004, 16:13
GoodBoy, если необходимо быстродействие, то ГОТО бывает нужен.

Автор: GoodBoy 23.12.2004, 16:13
sergej.z, ну не знаю... Разве что в Ассембллере... smile

Автор: sergejzr 23.12.2004, 16:20
Вроде мы в той теме обсуждали smile Я просто тоже всегда думал, что без ГОТО можно обойтись, пока не встретил исходники БД smile Каждый лишний такт В Системе-БД отражается на быстродействии. Вот там много чего на ГОТО.

Автор: Sun 23.12.2004, 16:27
Цитата(sergej @ 23.12.2004, 13:20)
Вроде мы в той теме обсуждали smile Я просто тоже всегда думал, что без ГОТО можно обойтись, пока не встретил исходники БД smile Каждый лишний такт В Системе-БД отражается на быстродействии. Вот там много чего на ГОТО.

Также как и в ядре ОС.

Автор: Akina 23.12.2004, 16:32
В BASIC без него никуда:
Код
ON ERROR GOTO label
smile

Автор: bel_nikita 23.12.2004, 16:32
правильное и грамотное применение goto нынче говорит о проффесионализме smile

Автор: dm9 23.12.2004, 17:03
Применение goto:
- Выход из цикла большой вложенности.
- Переход к выполнению набора действий по условиям, разбросанным по функции. Пример: при ошибке надо сказать пользователю, что произошла ошибка, освободить ресурсы и выйти из подпрограммы. Проверок на ошибку - несколько штук в этой подпрограмме. Тогда в конец функции помещают метку и за ней эти действия, при ошибке - goto label. В Паскале без этого обойтись можно вложенной функцией, в Си, насколько я знаю, нет.

Автор: Domestic Cat 23.12.2004, 19:49
Цитата
И еще почему даже в таких современных полностью ОО языках, как Java или C# он оставлен?


В Java его нет smile Есть только зарезервированноe словo goto - видимо собиралис' его вводить но потом отказались.

Автор: chipset 23.12.2004, 19:49
Цитата(dm9 @ 23.12.2004, 06:03)
- Переход к выполнению набора действий по условиям, разбросанным по функции

Механизм исключений?

Автор: Domestic Cat 23.12.2004, 20:03
Цитата
Механизм исключений?


Исклюхения очень неэффективны:
1. Растет размер кода (по крайней мере в Java размещение try-catch-finallы "развернется" в кучу всевозможных проверок - перепроверок и goto в байткоде).
2.Значительно снижается скорость кодa, т.к. при вызове методов из трай -блоков идеt запись дополнительнx параметров на стек.

Автор: chipset 23.12.2004, 20:04
Цитата(Domestic @ 23.12.2004, 09:03)
Исклюхения очень неэффективны:

Хороший код пишется с исключениями smile
Не знаю как у вас в Жабе.. но в плюсах именна так ;)

Автор: Domestic Cat 23.12.2004, 20:10
Цитата
Хороший код пишется с исключениями 



Исключения хороши для того, для чего они предназначены: ловить исключительные sитуации.
Но в любом языке (и в сиппипи) брошнный иксепшн означает (неэффективную) размотку sтекa;
а потому ими пользоваться нужnо в меру. goto был бы быстрее, хотя я считаю без негo в языках высокого уговня легкo можнo обойтись.

Автор: Domestic Cat 23.12.2004, 20:29
Java:
http://www.javaperformancetuning.com/tips/rawtips.shtml

Throwing/catching exceptions are tremendously expensive.


C++
http://www.informit.com/guides/content.asp?g=cplusplus&seqNum=112

Автор: Sardar 23.12.2004, 21:51
Цитата(dm9 @ 23.12.2004, 16:03)
- Выход из цикла большой вложенности.

Для этого не нужны goto, а break/continue с меткой.

Цитата(dm9 @ 23.12.2004, 16:03)
- Переход к выполнению набора действий по условиям, разбросанным по функции.

Не читабельный код, говорю по опыту раскапывания старого QVB(диалект VB) кода. Сколько себя помню goto не использовал smile

Автор: dm9 24.12.2004, 02:51
Sardar, для небольших ф-ций вполне читабельный.

Цитата(Sardar @ 23.12.2004, 21:51)
break/continue с меткой.

Это понятно, но в БОЛЬШОЙ вложенности тебе придётся делать кучу проверок для этих меток.

Автор: Domestic Cat 24.12.2004, 06:20
Цитата(dm9 @ 23.12.2004, 17:51)
Sardar, для небольших ф-ций вполне читабельный.


Для небольших методов goto и не нужен smile

Автор: chipset 24.12.2004, 10:59
Domestic Cat
А читабельность кода?
На мой взгляд, удобнее читать код с исключениями чем
заниматься сексом с goto'ами...

Автор: dm9 24.12.2004, 14:26
Цитата(Domestic @ 24.12.2004, 06:20)
Для небольших методов goto и не нужен


"Небольшой" понятие относительное. Я имею в виду нормальную функцию длиной в 2-3 экрана.

Потом, что значит "нечитабельный"? Насколько я знаю, goto сейчас применяется только для тех целей, которые я указал (99%).Стало быть, если нет цикла, то... В общем, структура кода достаточна очевидна. Однако, здесь дело каждого, как и что использовать. Мне лично немного непонятен лозунг "программирование без goto!!!". Почему без него? И с ним можно делать красивый код, только злоупотреблять не надо, как и везде.
Что, скажете, из цикла тройной-четверной вложенности вы выйдете красивее и понятнее при помощи доп. перепенных и break-ов? Да никогда smile

Автор: Girder 24.12.2004, 16:00
Цитата(dm9 @ 24.12.2004, 14:26)
только злоупотреблять не надо
Согласенен. Как говорится: Любое лекарство в больших количествах - вред!

PS: А без лекарства - можно "ласты склеить" smile

Автор: Domestic Cat 24.12.2004, 17:27
Цитата
А читабельность кода?


ну это само собой smile
а вообще я не помню чтобы я пользовался иксепшнами (как и goto) для переходов куда либо.

Цитата
Потом, что значит "нечитабельный"?


не всякий код с goto будет нечитабельным, но goto стимулирует написание такогo кода. при правильном пользовании goto можеt быть удобен, но будет ли приятно чи тать код поперемеченный лейбелами вдоль и поперек? все что может goto можно сделать другими средствами; возможно в некоторых (0.001%) ситуация такой код будет неуклюжим по сравнению с goto, но зато в остальных - будет понятнее.

Автор: dm9 24.12.2004, 17:39
Цитата(Domestic @ 24.12.2004, 17:27)
поперемеченный лейбелами вдоль и поперек?


Заметь, об этом никто не говорил smile)

Цитата(Domestic @ 24.12.2004, 17:27)
при правильном пользовании goto можеt быть удобен


Вот! И я о чём! smile

Автор: Domestic Cat 24.12.2004, 17:45
Цитата
Вот! И я о чём!


все равно - в Java его нет и я нe разу о нем нe вспомнил smile

Автор: Sardar 24.12.2004, 18:12
Цитата(dm9 @ 24.12.2004, 01:51)
Это понятно, но в БОЛЬШОЙ вложенности тебе придётся делать кучу проверок для этих меток.

Не понял про проверки. Гото это универсальный оператор перехода куда угодно(возможно ограничение: только внутри функции). break/continue с меткой имеет однозначное значение: окончить/продолжить заданный цикл. По любому компилятор сгенерит гото в конец или начало цикла, вместо того что бы ты сделал это сам. Я за goto, но что бы компилятор выдавал warning'и и обкладывал трёхступенчатым не отключаемым матом всех, кто захочет его использовать smile

Цитата(Domestic @ 24.12.2004, 16:45)
се равно - в Java его нет и я нe разу о нем нe вспомнил

Я тоже smile

Автор: chipset 25.12.2004, 03:32
Цитата(Domestic @ 24.12.2004, 06:27)
, но будет ли приятно чи тать код поперемеченный лейбелами вдоль и поперек?

Зато с исключениями гораздо логичнее заметь ;)

Автор: Domestic Cat 25.12.2004, 03:50
Вот stubborn smile
Без них еще логичнее smile

Автор: dm9 25.12.2004, 09:55
Цитата(Sardar @ 24.12.2004, 18:12)
Не понял про проверки. Гото это универсальный оператор перехода куда угодно(возможно ограничение: только внутри функции). break/continue с меткой имеет однозначное значение: окончить/продолжить заданный цикл. По любому компилятор сгенерит гото в конец или начало цикла, вместо того что бы ты сделал это сам. Я за goto, но что бы компилятор выдавал warning'и и обкладывал трёхступенчатым не отключаемым матом всех, кто захочет его использовать


Что-то я тебя не понял. Что такое goto я знаю smile
Я думал, ты хочешь выйти из цикла по break, но это выход из внутреннего цикла. Перед этим мы ставим флаг, и точно так же по break выходим из второго цикла. По этому же флагу - из третьего.
А что ты имел в виду под "break/continue с меткой"? Может, мы про разные языки? smile Я знаю break/continue в Паскале smile Но при чём тут метка (label, тот самый label, на который происходит goto?)

Автор: Domestic Cat 25.12.2004, 10:48
Цитата
Может, мы про разные языки? smile Я знаю break/continue в Паскале smile Но при чём тут метка (label, тот самый label, на который происходит goto?)


В Java возможна например такая конструкция:
Код

label:
  for (;; )
      for (;; )
          for (int i = 0; i < 100; i++)
                if (i == 55) break label;

Вот это и имелось в виду smile

Автор: dm9 25.12.2004, 10:50
Прикольно smile Не знал.

Автор: Sardar 25.12.2004, 16:33
dm9 это логичнее, так как ты просто помечаешь цикл из которого хочешь потом выйти. Когда узнал чт в Сях этого нет, сильно удивился...

Автор: dm9 25.12.2004, 22:20
Да, в современных языках делается всё, чтобы сделать ненужным применение goto smile

Автор: sergejzr 27.12.2004, 03:20
Да, но вот в сях её нет... поэтому там нужен GOTO smile
А так конечно прекрасная вещь, эти labels smile

Автор: chipset 19.1.2005, 15:59
Код

#define java_break goto

И никаких goto smile

Автор: dm9 19.1.2005, 16:47
smile
Добавлено @ 16:52
Если говорить про строго структурированное программирование, тогда к лозунгу "нет goto" можно добавить "нет break-ам, halt-ам, exit-ам, continue-сам". Что там ещё? smile

Автор: Domestic Cat 19.1.2005, 19:09
Брейки и continue - довольно слабая замена goto, для циклов, где пришлось бы иначе добавлять лишние проверки Чаще всего их легко отследить и проблем они не вызывают. Екзит прерывает выполнение программы, потому вопросов там вообще нет. А вот goto может применяться и в других целях.

Автор: Pakshin A. S. 19.1.2005, 19:20
ПРИВЕДИТЕ ПРИМЕР ПРОГРАММЫ НА ПАСКАЛЕ ИЛИ DELPHI, в которой НЕЛЬЗЯ обойтись без GOTO!!! smile

Любой GOTO может быть заменен: циклом, дополнительным условием в цикле, выбором... smile

Автор: dm9 19.1.2005, 19:37
Pakshin A. S., что доказывается в курсе дискретной математики...

Вот только вопрос не в том, что можно, а в том, что удобно.

Я могу привести как минимум один случай на Паскале и два на Си, когда GoTo удобен. Вернее, я уже приводил эти примеры выше.

Главное, без фанатизма smile
Добавлено @ 19:37
Вернее, на Паскале тоже два случая, но с горем пополам один можно заменить вложенной функцией...

Автор: Pakshin A. S. 19.1.2005, 19:40
Гы... мне ее (дискретку) как раз 24-ого сдавать... smile smile smile


А ну дай эти случаи... smile

Автор: dm9 19.1.2005, 19:45
Цитата(dm9 @ 23.12.2004, 17:03)
Применение goto:
- Выход из цикла большой вложенности.
- Переход к выполнению набора действий по условиям, разбросанным по функции. Пример: при ошибке надо сказать пользователю, что произошла ошибка, освободить ресурсы и выйти из подпрограммы. Проверок на ошибку - несколько штук в этой подпрограмме. Тогда в конец функции помещают метку и за ней эти действия, при ошибке - goto label. В Паскале без этого обойтись можно вложенной функцией, в Си, насколько я знаю, нет.


Автор: Sardar 19.1.2005, 20:50
Цитата(dm9 @ 19.1.2005, 18:45)
Выход из цикла большой вложенности.

dm9, на счёт этого у тебя просто "запаянная память" smile smile Циклы логически нужно помечать именнами или уровнями без разницы и командами break/continue продолжать или прерывать требуемый цикл, это логично smile
Это всё равно что передавать в таких языках как JS, Ptyhon и подобных обьект функцию, как нормальный обьект, а не указатель как в C/C++ - что есть домысливание(шаблон) программиста.

Возможно еще более контрастный пример, зачем нам while? Ведь метка + условный блок(if) + goto делают то же самое, попробуй программисту на асме доказать обратное smile

Цитата(dm9 @ 19.1.2005, 18:45)
Переход к выполнению набора действий по условиям, разбросанным по функции. Пример: при ошибке надо сказать пользователю, что произошла ошибка, освободить ресурсы и выйти из подпрограммы. Проверок на ошибку - несколько штук в этой подпрограмме. Тогда в конец функции помещают метку и за ней эти действия, при ошибке - goto label. В Паскале без этого обойтись можно вложенной функцией, в Си, насколько я знаю, нет.

Это устаревшая логика/мышление smile Есть и более продвинутые модели, такие как исключения и прочее smile

Автор: dm9 20.1.2005, 00:45
Цитата(dm9 @ 19.1.2005, 19:37)
Я могу привести как минимум один случай на Паскале и два на Си, когда GoTo удобен.


Именно так и читать. "Паскаль" и "Си".
Не "С++", не "Delphi", не "Java", не "C#" и так далее.

Хотя в том же Delphi покажи мне способ выхода из цикла большой вложенности. Я знаю только один.

Код
for i := 1 to 100 do
begin
  if (b) then break;
  for j := 1 to 100 do
  begin
     if (b) then break;
     for k := 1 to 100 do
     begin
        if (b) then break;
        for m := 1 to 100 do
        begin
           ...
           if (cond) then
           begin
              b := true;
              break;
           end;
        end;

     end;
  end;
end;


Так попроще будет:

Код
label1:
for i := 1 to 100 do
begin
  for j := 1 to 100 do
  begin
     for k := 1 to 100 do
     begin
        for m := 1 to 100 do
        begin
           ...
           if (cond) then goto label1;
        end;

     end;
  end;
end;

Автор: dm9 19.2.2005, 15:33
Вот, кстати, о чём я говорил (обработка ошибок).
Пришлось сегодня глянуть на исходник regsvr...

Обратить внимание на строчки

Код
CleanupLibrary:
       FreeLibrary(hLib);
   }

CleanupOle:
   OleUninitialize();


Имхо, достаточно красиво smile

Код
// regsvr.cpp : Program to invoke OLE self-registration on a DLL.
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

#include <windows.h>
#include <ole2.h>
#include <tchar.h>
#include <stdio.h>
#include "resource.h"

#define FAIL_ARGS   1
#define FAIL_OLE    2
#define FAIL_LOAD   3
#define FAIL_ENTRY  4
#define FAIL_REG    5

const TCHAR _szAppName[] = _T("RegSvr32");
const char _szDllRegSvr[] = "DllRegisterServer";
const char _szDllUnregSvr[] = "DllUnregisterServer";
HINSTANCE _hInstance;

BOOL _bSilent;
BOOL _bConsole;

#define SafePutts(string) ((stdout >= 0) ? _putts(string) : 0)

void
FormatString2(
   LPTSTR lpszOut,
   LPCTSTR lpszFormat,
   LPCTSTR lpsz1,
   LPCTSTR lpsz2
   )
{
   LPCTSTR pchSrc = lpszFormat;
   LPTSTR pchDest = lpszOut;
   while (*pchSrc != '\0') {
       if (pchSrc[0] == '%' && (pchSrc[1] >= '1' && pchSrc[1] <= '2')) {
           lstrcpy(pchDest, (LPCTSTR)(pchSrc[1] == '1' ? lpsz1 : lpsz2));
           pchDest += lstrlen(pchDest);
           pchSrc += 2;
       } else {
           if (_istlead(*pchSrc))
               *pchDest++ = *pchSrc++; // copy first of 2 bytes
           *pchDest++ = *pchSrc++;
       }
   }
   *pchDest = '\0';
}

#define MAX_STRING 1024

void
DisplayMessage(
   UINT ids,
   LPCTSTR pszArg1 = NULL,
   LPCTSTR pszArg2 = NULL,
   BOOL bUsage = FALSE,
   BOOL bInfo = FALSE
   )
{
   if (_bSilent && !_bConsole)
       return;

   TCHAR szFmt[MAX_STRING];
   LoadString(_hInstance, ids, szFmt, MAX_STRING);

   TCHAR szText[MAX_STRING];
   FormatString2(szText, szFmt, pszArg1, pszArg2);
   if (bUsage) {
       int cch = _tcslen(szText);
       LoadString(_hInstance, IDS_USAGE, szText + cch, MAX_STRING - cch);
   }

   if (! _bSilent)
       MessageBox(NULL, szText, _szAppName,
           MB_TASKMODAL | (bInfo ? MB_ICONINFORMATION : MB_ICONEXCLAMATION));

   if (_bConsole) {
       TCHAR szMessage[MAX_STRING];
       FormatString2(szMessage, _T("%1: %2\n"), _szAppName, szText);
       SafePutts(szMessage);
   }
}

inline void
Usage(
   UINT ids,
   LPCTSTR pszArg1 = NULL,
   LPCTSTR pszArg2 = NULL
   )
{
   DisplayMessage(ids, pszArg1, pszArg2, TRUE);
}

inline void
Info(
   UINT ids,
   LPCTSTR pszArg1 = NULL,
   LPCTSTR pszArg2 = NULL
   )
{
   DisplayMessage(ids, pszArg1, pszArg2, FALSE, TRUE);
}

int PASCAL
WinMain(
   HINSTANCE hInstance,
   HINSTANCE,
   LPSTR,
   int
   )
{
   int iReturn = 0;
   HRESULT (STDAPICALLTYPE * lpDllEntryPoint)(void);

   BOOL bVisualC = FALSE;
   BOOL bUnregister = FALSE;
   LPCSTR pszDllEntryPoint = _szDllRegSvr;
   LPCSTR pszDllName = NULL;
   LPCSTR pszTok;

   _hInstance = hInstance;

   // Parse command line arguments.
   int iTok;
   for (iTok = 1; iTok < __argc; iTok++) {
       pszTok = __argv[iTok];

       if ((pszTok[0] == '-') || (pszTok[0] == '/')) {
           switch (pszTok[1]) {
               case 'v':
               case 'V':
                   bVisualC = TRUE;
                   break;

               case 's':
               case 'S':
                   _bSilent = TRUE;
                   break;

               case 'u':
               case 'U':
                   bUnregister = TRUE;
                   pszDllEntryPoint = _szDllUnregSvr;
                   break;

               case 'c':
               case 'C':
                   _bConsole = TRUE;
                   break;

               default:
                   Usage(IDS_UNRECOGNIZEDFLAG, pszTok);
                   return FAIL_ARGS;
           }
       } else {
           if (pszDllName == NULL) {
               pszDllName = pszTok;
               break;
           } else {
               Usage(IDS_EXTRAARGUMENT, pszTok);
               return FAIL_ARGS;
           }
       }
   }

   if (pszDllName == NULL) {
       if (bVisualC)
           DisplayMessage(IDS_NOPROJECT);
       else
           Usage(IDS_NODLLNAME);

       return FAIL_ARGS;
   }

   // Initialize OLE.
   if (FAILED(OleInitialize(NULL))) {
       DisplayMessage(IDS_OLEINITFAILED);
       return FAIL_OLE;
   }

   SetErrorMode(SEM_FAILCRITICALERRORS);       // Make sure LoadLib fails.
   for (; iTok < __argc; iTok++) {
       pszDllName = __argv[iTok];

       // Load the library.
       HINSTANCE hLib = LoadLibraryEx(pszDllName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);

       if (hLib < (HINSTANCE)HINSTANCE_ERROR) {
           TCHAR szError[12];
           wsprintf(szError, _T("0x%08lx"), GetLastError());
           DisplayMessage(IDS_LOADLIBFAILED, pszDllName, szError);
           iReturn = FAIL_LOAD;
           goto CleanupOle;
       }

       // Find the entry point.
       (FARPROC&)lpDllEntryPoint = GetProcAddress(hLib, pszDllEntryPoint);

       if (lpDllEntryPoint == NULL) {
           TCHAR szExt[_MAX_EXT];
           _tsplitpath(pszDllName, NULL, NULL, NULL, szExt);

           if ((_stricmp(szExt, ".dll") != 0) && (_stricmp(szExt, ".ocx") != 0))
               DisplayMessage(IDS_NOTDLLOROCX, pszDllName, pszDllEntryPoint);
           else
               DisplayMessage(IDS_NOENTRYPOINT, pszDllName, pszDllEntryPoint);

           iReturn = FAIL_ENTRY;
           goto CleanupLibrary;
       }

       // Call the entry point.
       if (FAILED((*lpDllEntryPoint)())) {
           DisplayMessage(IDS_CALLFAILED, pszDllEntryPoint, pszDllName);
           iReturn = FAIL_REG;
           goto CleanupLibrary;
       }

       Info(IDS_CALLSUCCEEDED, pszDllEntryPoint, pszDllName);

CleanupLibrary:
       FreeLibrary(hLib);
   }

CleanupOle:
   OleUninitialize();

   return iReturn;
}

Автор: Sardar 19.2.2005, 17:20
dm9 порой людей исправляет только могила smile smile

Автор: Дрон 19.2.2005, 20:35
Цитата(Sardar @ 19.2.2005, 17:20)
dm9 порой людей исправляет только могила smile smile

Это ты обо что?

Автор: dm9 19.2.2005, 20:52
Цитата(Sardar @ 19.2.2005, 17:20)
dm9 порой людей исправляет только могила


smile

Автор: Sardar 19.2.2005, 21:40
Цитата
Это ты обо что?

Не хотел обидеть smile Просто иногда какие то идеи так вживаются в человека, что альтернативы не уже воспринимаются. Например есть люди, считающие что цикл это For I=.. To .. - т.е. целочисленный счётчик, всё другое есть ересь по определению.

Автор: Дрон 19.2.2005, 21:48
Цитата(Sardar @ 19.2.2005, 21:40)
Просто иногда какие то идеи так вживаются в человека, что альтернативы не уже воспринимаются. Например есть люди, считающие что цикл это For I=.. To .. - т.е. целочисленный счётчик, всё другое есть ересь по определению

Понятно.
На самом деле я сторонник goto в вышепреведённой ситуации. И только в ней smile

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

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)