goto
는 거의 일반적으로 권장되지 않습니다. 이 문장을 사용할 가치가 있습니까?
댓글
Answer
이것은 Stack Overflow에서 여러 번 논의되었으며 Chris Gillum은 goto
의 가능한 사용을 요약했습니다.
완전히 함수 종료
종종 함수에서 리소스를 할당하고 여러 위치에서 종료해야 할 수 있습니다. 프로그래머는 함수의 모든 ” 종료 지점 “이 이동하는 함수 끝에 리소스 정리 코드를 배치하여 코드를 단순화 할 수 있습니다. 정리 레이블. 이렇게하면 함수의 모든 ” 종료 지점 “에서 정리 코드를 작성할 필요가 없습니다.
중첩 된 루프 종료
중첩 된 루프에 있고 모든 루프에서 goto는 break 문과 if-check보다 훨씬 더 깔끔하고 간단하게 만들 수 있습니다.
낮은 수준의 성능 개선
이것은 성능이 중요한 코드에서만 유효하지만 goto 문은 매우 빠르게 실행되며 함수를 이동할 때 도움이 될 수 있습니다. 그러나 이것은 컴파일러가 일반적으로 gotos를 포함하는 코드를 최적화 할 수 없기 때문에 양날의 검입니다.
나는 다른 많은 사람들이 주장 하듯이 주장합니다. , 이러한 모든 경우에서 goto
의 사용은 자신을 코딩 한 코너에서 벗어나는 수단으로 사용되며 일반적으로 리팩토링 할 수있는 코드의 증상입니다. .
댓글
- 첫 번째 문제는 현대 언어의
finally
블록에 의해 매우 깔끔하게 해결됩니다. 두 번째는break
레이블이 지정되어 해결됩니다. ‘하지만 C를 고수하는 경우goto
는 이러한 문제를 우아하게 해결하는 유일한 방법입니다. - 매우 좋은 점입니다. Java가 여러 수준의 루프에서 벗어나는 방법이 마음에 듭니다.
- @Chinmay-finally blocks only 1) 현대 언어에 적용하고 b) 오버 헤드를 견딜 수 있습니다 (예외 처리에는 오버 헤드가 있습니다. ) 즉,
finally
사용은 해당 조건에서만 유효합니다. 매우 드물지만 유효한 상황에서 goto가 갈 길입니다. - 좋아요 … 도대체 무엇이
break 3
또는break myLabel
및goto myLabel
. 아, ‘ 바로 키워드입니다.break
,continue
또는 유사한 키워드를 사용하는 경우 실제로goto
를 사용하고있는 것입니다. (for, while, foreach, do/loop
를 사용하는 경우 조건부 goto를 사용하는 것입니다.) - 낮은 수준의 성능 정보-최신 프로세서의 동작을 예측하기 어려울 수 있습니다 (파이프 라인, 비 순차적 실행) 따라서 아마도 99 %의 경우 가치가 없거나 느릴 수도 있습니다. @MatthewWhited : 범위 지정. 임의의 지점에서 범위를 입력하면 어떤 생성자를 호출해야하는지 (인간에게) 명확하지 않습니다 (문제는 C에도 존재합니다).
답변
상위 수준의 제어 흐름 구조는 문제 영역의 개념과 일치하는 경향이 있습니다. if / else는 어떤 조건에 기반한 결정입니다. 루프는 몇 가지 작업을 반복적으로 수행하도록 말합니다. break 문조차도 “이 작업을 반복해서 수행했지만 이제 중단해야합니다”라고 말합니다.
반면에 goto 문은 실행중인 프로그램의 개념에 해당하는 경향이 있습니다. 문제 영역. 프로그램의 지정된 지점에서 실행을 계속하라는 메시지입니다. 코드를 읽는 사람은 문제 영역과 관련하여 그것이 의미하는 바를 추론 해야합니다.
물론 모든 상위 수준 구조는 gotos 및 간단한 조건 분기로 정의 할 수 있습니다. . 그것은 “그들이”단순히 변장했다는 것을 의미하지는 않습니다. 그것들을 제한된 gotos라고 생각하세요. 그리고 그것들을 유용하게 만드는 것은 제한입니다. break 문은 둘러싸는 루프의 끝으로의 점프로 구현되지만, 다음과 같이 생각하는 것이 더 좋습니다. 전체적으로 루프에서 작동합니다.
다른 모든 것이 동일하면 문제 도메인의 구조를 반영하는 코드는 읽기 및 유지 관리가 더 쉬운 경향이 있습니다.
goto 문은 절대적으로 필요하지만 (해당 효과에 대한 “정리 는” 정리 ) 가장 나쁜 해결책이 될 수있는 경우가 있습니다. 언어가 지원하는 상위 수준 구조에 따라 언어 간.
예를 들어 C에서는 goto가 적절한 세 가지 기본 시나리오가 있다고 생각합니다.
- 중첩 된 루프에서 벗어나기. 언어에 레이블이 지정된 break 문이있는 경우에는 필요하지 않습니다.
- 오류 또는 기타 예기치 않은 이벤트가 발생한 경우 코드 확장 (일반적으로 함수 본문)에서 벗어나기 . 언어에 예외가있는 경우에는 불필요합니다.
- 명시적인 유한 상태 머신 구현. 이 경우 (그리고이 경우에만) goto는 문제 영역의 개념에 직접 대응하여 한 상태에서 지정된 다른 상태로 전환합니다. 여기서 현재 상태는 현재 실행중인 코드 블록으로 표시됩니다. .
반면에 명시 적 유한 상태 머신은 루프 내부의 switch 문으로 구현 될 수도 있습니다. 예를 들어 디버깅에 유용 할 수있는 코드의 동일한 위치에서 모든 상태가 시작된다는 이점이 있습니다.
합리적으로 현대적인 언어 (if /를 지원하는 언어에서 goto의 주요 사용) else and loops)는 “언어에서 누락 된 제어 흐름 구조를 시뮬레이션하는 것입니다.
댓글
- 실제로 지금까지 가장 좋은 답변입니다. – 1 년 반 된 질문의 경우 다소 놀랍습니다. 🙂
- +1 ~ ” 지금까지의 베스트 답변 “. — ” 합리적으로 현대적인 언어 (if / else 및 루프를 지원하는 언어)에서 goto의 주요 용도는 제어 흐름을 시뮬레이션하는 것입니다. 언어에서 누락 된 ‘를 구성합니다. ”
- switch-statement 상태 시스템에서 모든 쓰기는 제어 값은 실제로
goto
입니다. SSSM ‘는 종종 사용하기에 좋은 구조입니다. 실행 구조에서 SM 상태를 구문 분석하지만 ‘ ” gotos “. - ” 다른 모든 것이 동일하며, 구조가 문제 도메인의 구조를 반영하는 코드는 읽고 유지하기가 더 쉽습니다. ” ‘이 사실을 오랫동안 완전히 알고 있었지만 다른 사람과 다른 방식으로 정확하게 전달할 수있는 단어가 부족했습니다. 프로그래머는 실제로 이해할 수 있습니다. 감사합니다.
- ” 구조화 된 프로그램 정리 “는 다음을 명확하게 보여주기 때문에 저를 즐겁게합니다. 구조화 된 프로그래밍 문을 사용하여 goto를 에뮬레이트하는 것은 goto를 사용하는 것보다 훨씬 읽기 어렵습니다!
Answer
물론 프로그래밍 언어에 따라 다릅니다. goto
가 논란의 여지가있는 주된 이유는 컴파일러가 너무 자유롭게 사용하도록 허용 할 때 발생하는 악영향 때문입니다. 예를 들어, goto
를 사용하여 초기화되지 않은 변수에 액세스 할 수 있거나 더 나쁜 경우 다른 메서드로 이동하여 호출을 엉망으로 만들 수있는 경우 문제가 발생할 수 있습니다. 스택. 무의미한 제어 흐름을 허용하지 않는 것은 컴파일러의 책임이어야합니다.
Java는 goto
를 완전히 허용하지 않음으로써이 문제를 “해결”하려고했습니다. 그러나 Java를 사용하면 finally
블록 내에서 return
를 사용할 수 있으므로 실수로 예외를 삼킬 수 있습니다.동일한 문제가 여전히 존재합니다. 컴파일러가 작업을 수행하지 않습니다. 언어에서 goto
를 제거해도 문제가 해결되지 않았습니다.
C #에서 goto
는
, continue
, try/catch/finally
및 return
. 초기화되지 않은 변수를 사용할 수없고 finally 블록에서 뛰어 내릴 수 없습니다. 컴파일러가 불평 할 것입니다. 이것은 내가 말도 안되는 제어 흐름이라고 말한 것과 같은 실제 문제를 해결하기 때문입니다. goto
는 확정 할당 분석 및 기타 합리적인 컴파일러 검사를 마술처럼 취소하지 않습니다.
댓글
- 요점은 C # ‘의
goto
가 나쁘지 않다는 것입니다. 그렇다면 C # …
뿐만 아니라 goto
구문을 사용하여 일상적으로 사용되는 모든 현대 언어에 해당됩니다. 답변
예. 루프가 여러 수준 깊이 중첩 된 경우 goto
는 내부 루프에서 우아하게 벗어나는 유일한 방법입니다. 다른 옵션은 플래그를 설정하고 해당 플래그가 조건을 충족하는 경우 각 루프를 중단하는 것입니다. 이것은 정말 추하고 오류가 발생하기 쉽습니다. 이 경우 goto
가 더 낫습니다.
물론 break
문으로 레이블이 지정된 Java “가 동일합니다. 하지만 코드에서 임의의 지점으로 이동할 수 없도록하여 goto
를 악하게 만드는 것을 허용하지 않고 문제를 깔끔하게 해결합니다.
댓글
- goto는 결코 우아한 대답이 아닙니다. 루프가 여러 수준 깊이 중첩 될 때 문제는 다중 중첩 루프를 피하기 위해 코드를 설계하지 못한 것입니다. 프로 시저 호출은 그렇지 않습니다. (” Lambda : The Ultimate … ” 문서 읽기) goto를 사용하여 여러 중첩 된 루프에서 깊이 수준은 개방형 다중 골절에 반창고를 붙이는 것입니다. 간단 할 수 있지만 정답은 아닙니다. ‘
- 물론 거기에 있습니다. 깊이 중첩 된 루프가 호출되는 경우는 결코 이상한 경우가 아닙니까? 좋은 프로그래머가되는 것은 아닙니다. 규칙을 따르는 것뿐만 아니라 규칙을 어길 때를 아는 것도 중요합니다.
- @ JohnR.Strohm 절대로 말하지 마십시오. 프로그래밍에서 ” 절대 “와 같은 용어를 사용한다면 ‘ 분명히 다루지 않은 것입니다. 코너 케이스, 최적화, 리소스 제한 등이 있습니다. 깊게 중첩 된 루프에서 goto 는 실제로 루프를 종료하는 가장 깨끗하고 우아한 방법입니다. 코드를 얼마나 리팩토링했는지 ‘ 문제가되지 않습니다. ‘
- @ JohnR.Strohm : 두 번째로 놓친 부분 VB.NET에서 C #으로 전환 할 때 기능 :
Do
루프. 왜?Do
루프로 딥 브레이크가 필요한 하나의 루프를 변경하고Exit Do
를 입력하면 ‘는GoTo
가 아닙니다. 중첩 루프는 항상 발생합니다. 스택을 깨는 일이 거의 발생합니다. - @ JohnR.Strohm ” goto를 말하는 유일한 이유는 결코 우아한 대답이 아닙니다. “는 goto가 결코 우아한 대답이 아니므로 goto를 사용하는 어떤 솔루션도 우아한 대답이 될 수 없다는 것을 결심했기 때문입니다.
답변
대부분의 낙담은 “60 년대 초반”에 대한 무차별적인 힘을 강요했던 신 지크 스트라가 만든 일종의 “종교”에서 비롯됩니다. :
- 어떤 코드 블록 으로든 점프
- 시작부터 실행되지 않는 함수
- 처음부터 실행되지 않은 루프
- 변수 초기화 건너 뛰기
- 가능한 정리없이 코드 블록에서 뛰어 내립니다.
이것은 goto
현대 언어에 대한 설명으로, 그 존재는 단순히 cr을 지원하기 때문입니다. 제공되는 언어 이외의 코드 구조.
특히 위의 첫 번째 요점은 더 이상 허용되고 두 번째 요점은 정리됩니다 (goto
스택이 제대로 풀리고 모든 적절한 소멸자가 호출됩니다.)
이 답변 을 참조하여 코드가 얼마나 균일하지 않은지 알 수 있습니다. goto를 사용하면 읽을 수 없습니다. 문제는 goto 자체가 아니라 그것을 잘못 사용하는 것입니다.
if
를 사용하지 않고 전체 프로그램을 작성할 수 있습니다. for
. 물론 읽기 어렵고 서투르고 불필요하게 복잡해 보입니다.
그러나 문제는 for
가 아닙니다. 나야.
break
, continue
, throw
,
등은 Djikstrarian 광신도의 초승달 모양의 시미 터에서 탈출하기 위해 가장 무도회 goto
이상을 지적합니다. 현대 laguages가 발명 된 지 50 년이 지난 지금도 여전히 죄수를 원합니다. 그들은 Djikstra가 말하는 것을 잊어 버렸고, 그의 노트의 제목 만 기억하고 (GOTO는 유해한 것으로 간주했고, 그의 onw 제목조차도 편집자가 변경하지 않았습니다.) 4 개의 모든 구성물을 비난하고 비난하고 비난하고 비난합니다. 순서대로 배치 된 문자입니다.
2011 년입니다. 이제 goto
가 GOTO
Djikstra가 설득력있는 진술.
댓글
- ” 휴식, 계속 , throw, bool needed = true; (필요) {…} 등은 가장 무도회 고토 이상을 언급하고 있습니다 ” 나는 그것에 동의하지 않습니다 ‘. ” 휴식 등과 같은 것은 제한된 goto ” 또는 이와 유사한 것을 선호합니다. goto의 주요 문제는 일반적으로 너무 강력하다는 것입니다. 현재 goto가 Dijkstra ‘보다 덜 강력하다는 점에서 귀하의 대답은 괜찮습니다.
- @MuhammadAlkarouri : 전적으로 동의합니다. 내 개념을 정확하게 표현할 수있는 더 나은 문구를 방금 찾았습니다. 내 요점은 이러한 제한이 때때로 적용되지 않을 수 있으며 필요한 제한의 종류가 언어에 없다는 것입니다. 그런 다음보다 ” 강력하고 ” 덜 전문화되어 문제를 해결할 수 있습니다. 예를 들어 Java
break n
는 C ++에서 사용할 수 없으므로escape
div 인 경우에도goto escape
>는 n-ple 루프에서 벗어날 필요가 없습니다.
답변
여기에 이상한 goto 또는 함수에 국한되어있는 한 가독성을 크게 떨어 뜨리는 경우는 거의 없습니다.이 코드에서 다소 드문 제어 구조를 사용해야하는 비정상적인 일이 발생하고 있다는 사실에주의를 기울임으로써 종종 이점을 얻습니다. .
(로컬) gotos가 가독성을 크게 저하시키는 경우 일반적으로 goto를 포함하는 함수가 너무 복잡해 졌다는 신호입니다.
내가 입력 한 마지막 goto C 코드의 일부는 한 쌍의 연동 루프를 구축하는 것이 었습니다. “허용되는”goto 사용에 대한 일반적인 정의에 맞지 않지만 그 결과 함수가 훨씬 더 작고 명확 해졌습니다. goto를 피하기 위해 DRY의 특히 지저분한 위반이 필요했을 것입니다.
Comments
- 이에 대한 대답은 이전 ” 레이 ‘의 감자 칩 ” 슬로건 : ” 하나만 먹을 수는 없습니다 ‘ “. 귀하의 예에는 두 개의 ” 연동 “이 있습니다 (무슨 뜻이든, 저는 ‘ 그것이 ‘ 아름다운 루프가 아니라고 확신합니다. 고토는 당신에게 값싼 것을주었습니다. 버스에 치인 후 코드를 수정해야하는 유지 보수 담당자는 어떻습니까? 고토가 그의 삶을 더 쉽게 만들까요, 더 어렵게 만들까요? 이 두 루프에 대해 재고해야합니까?
답변
이 모든 문제가 짖는 경우라고 생각합니다. 잘못된 나무입니다.
GOTO는 “나에게 문제가되지 않는 것 같지만, 오히려 실제 죄인 스파게티 코드”의 증상입니다.
GOTO가 원인 인 경우 흐름 제어 라인의 주요 교차점은 “나쁜 기간”입니다. 흐름 제어 라인을 통과하지 않으면 무해합니다. 그 사이의 회색 영역에는 루프 구제 금융과 같은 것들이 있지만 “합법적 인 모든 회색 사례를 포괄하는 구조를 추가하지 않은 언어가 아직 있습니다.
실제로 사용하는 유일한 사례입니다. 수년 동안 결정 지점이 루프의 중간에있는 루프의 경우입니다. 중복 된 코드, 플래그 또는 GOTO가 남았습니다. 저는 GOTO 솔루션이 세 가지 중 가장 좋은 방법이라고 생각합니다. 여기에는 흐름 제어 라인이 교차하지 않으며 무해합니다.
코멘트
- 당신이 언급 한 사례는 때때로“loop and a half”또는“N plus one half loop”라고 불리며 (언어가 허용하는 경우; 중간 루프에서 점프하는 다른 경우는 일반적으로
goto
없이는 사소합니다. ). - (아아, 대부분의 언어는 루프로 점프하는 것을 금지합니다.)
- @KonradRudolph : ” 루프
GOTO를 사용하면 점프 할 다른 루프 구조가 없습니다.
-
goto
는 여기에있는 제어 흐름은 ‘ 정상적인 구조 프로그래밍에 적합하지 않습니다. 패턴 . 구조화 된 프로그래밍 패턴에 맞는 제어 흐름은 그렇지 않은 것보다 추론하기가 더 쉽기 때문에 ‘ 가능하면 이러한 패턴을 사용해야합니다. 코드가 이러한 패턴에 맞으면 ‘ 그렇지 않다고 외쳐서는 안됩니다 ‘. 반면에 코드가 이러한 패턴에 실제로 맞지 않는 경우 ‘ 코드가 실제로 맞지 않을 때 코드가 맞는 척하는 것보다 ‘ 소리 치는 것이 좋습니다. ‘ t. - @supercat 음, 당신이 자신에게 일정을 썼는데 바람이 당신의 손에서 그것을 날린다 고 상상해보세요. 논리에 따르면 ‘ 일정을 추적하는 것이 일정에 맞지 않았으므로 ‘ 검색해서는 안됩니다.
답변
예, goto를 사용하여 개발자의 경험을 향상시킬 수 있습니다. http://adamjonrichardson.com/2012/02/06/long-live-the-goto-statement/
그러나 다른 강력한 도구 (포인터, 다중 상속 등)와 마찬가지로 훈련을 받아야합니다. 그것을 사용합니다. 링크에 제공된 예제는 PHP를 사용하여 goto 구문의 사용을 동일한 함수 / 메소드로 제한하고 새 제어 블록 (예 : 루프, switch 문 등)으로 점프하는 기능을 비활성화합니다.
답변
언어에 따라 다릅니다. 예를 들어 여전히 Cobol 프로그래밍에서 널리 사용되고 있습니다. 또한 펌웨어 프로그래밍 언어가 Goto를 사용해야하는 초기 BASIC 방언 인 Barionet 50 장치에서도 작업했습니다.
Answer
goto
는 레거시 어셈블러 코드를 C로 포팅 할 때 유용 할 수 있습니다. 어셈블러의 branch
명령어 대신 goto
를 사용하여 명령어에 의한 C로 변환하면 매우 빠른 포팅이 가능합니다.
코멘트
- 정답이지만
goto
에 대한 주장 중 하나는 컴파일러 최적화를 방해한다는 것입니다. - @Sapphire_Brick : 많은 컴파일러 최적화가 특정 실행 패턴을 중심으로 설계되었습니다. 수행 할 작업이 지원되는 실행 패턴에 맞지 않는 경우 ‘ ” ” 최적화를 방해하지 않을 수 있습니다. 나쁜 것입니다.
답변
아니요. 항상 goto가 해결하는 데 사용되는 문제에 더 구체적인 도구로 교체해야합니다 (사용자의 언어로 사용할 수없는 경우). 예를 들어 break 문과 예외는 이전에 goto에서 해결 한 루프 이스케이프 문제를 해결합니다. 오류 처리.
댓글
- 나는 ‘ 언어가 둘 다 이러한 기능,
goto
는 일반적으로 해당 언어에 없습니다. - 하지만 ‘ 필요하지 않거나 사람들 이 필요하지 않다고 생각해서 ‘
- 당신의 견해가 편협합니다.
goto
는 문제가되는 도메인 의미론에 가장 가까운 것입니다. 그 밖의 모든 것은 더티 해킹 일 것입니다. - @ SK-logic : I don ‘ ” 편협한 “라는 단어가 당신이 생각하는 의미를 의미한다고 생각하지 않습니다.
- @Keith,
자신의 의견과 편견에 충실하게 헌신 “-‘ 이 goto-bashing 눈가리개로 여기에서 일관되게 관찰하십시오. “ 항상 교체해야 ” 열광적 ‘ 적어도 말. 적절하고 건전한 의견에 가까운 것은 없지만 순수한 편견입니다. 이 ” 항상 “는 다른 의견을위한 공간을 남기지 않습니다.
답변
아니요. GOTO를 사용해야하는 경우 코드를 다시 디자인해야합니다.
댓글
- 아마도 ‘ 어떤 추론도 제공하지 않았습니다.
- Dijkstra는 수십 년 전에 추론을 자세하게 제공했습니다.
- Just Dogma. 공명이 없습니다. 참고 : Djikstra는 더 이상 유효한 이유가 아닙니다. 초기 ‘ 60 년대의 BASIC 또는 FORTRAN GOTO 문을 참조했습니다. 그들은 오늘날의 정말 빈혈 (그 힘에 비하면)과는 아무 관련이 없습니다.
- @EmilioGaravaglia 오늘날에도 여전히 적용되는 그의 추론의 일부는 ‘ 많은 gotos에 방법을 사용하여 스파게티 코드를 작성하는 것이 매우 쉽다는 것입니다. 그러나이 논리에 따라 ‘ 포인터를 사용하지 않아야합니다.
number of gotos needed to create problems
만큼 많은 포인터를 사용하면 유사한 혼란이 발생하기 때문입니다.
goto
는 CPU가 궁극적으로 수행하는 작업이지만 대상에 표시가 없기 때문에 인간이 이해하고 추상화하는 데 필요한 작업에는 적합하지 않습니다. 종료. IntercalCOMEFROM
와 비교해보세요.goto
는 필요하지 않습니다. 명령형 언어로 구현하는 가장 합리적인 방법 일뿐입니다. 상태 전환의 의미에 가장 가까운 것이기 때문입니다. 대상이 소스에서 상당히 멀어 ‘ 가독성을 방해하지 않습니다. 그러한 코드의 가장 좋아하는 예는 D.E. Knuth ‘의 Adventure 게임 구현