C ++에서 예외의 관용적 사용법


16

isocpp.org 예외 FAQ

함수 사용시 코딩 오류를 나타 내기 위해 throw를 사용하지 마십시오. 프로세스를 디버거로 보내거나 프로세스를 중단하고 개발자가 디버그 할 크래시 덤프를 수집하려면 assert 또는 기타 메커니즘을 사용하십시오.

반면에 표준 라이브러리는 std :: logic_error 및 모든 파생물을 정의합니다.이 파생물은 다른 것 외에도 프로그래밍 오류를 처리 해야하는 것처럼 보입니다. 프로그래밍 오류가 아닌 빈 문자열을 std :: stof (valid_argument를 던짐)에 전달합니까? '1'/ '0'과 다른 문자를 포함하는 문자열을 프로그래밍 오류가 아닌 std :: bitset (invalid_argument를 던짐)에 전달합니까? 프로그래밍 오류가 아닌 잘못된 인덱스로 std :: bitset :: set을 호출합니까 (out_of_range가 발생합니까)? 그렇지 않은 경우 테스트 할 프로그래밍 오류는 무엇입니까? std :: bitset 문자열 기반 생성자는 C ++ 11 이후에만 존재하므로 예외를 관용적으로 설계하여 설계해야합니다. 반면에 나는 사람들에게 logic_error가 기본적으로 전혀 사용되어서는 안된다고 말합니다.

예외와 함께 자주 발생하는 또 다른 규칙은 "예외 상황에서만 예외 사용"입니다. 그러나 라이브러리 함수는 어떤 상황이 예외적인지 어떻게 알 수 있습니까? 일부 프로그램의 경우 파일을 열 수없는 것이 예외 일 수 있습니다. 다른 사람들에게는 메모리를 할당 할 수없는 것이 예외적이지 않을 수 있습니다. 그리고 그 사이에 수백 가지의 사례가 있습니다. 소켓을 만들 수 없습니까? 소켓이나 파일에 데이터를 연결하거나 쓸 수 없습니까? 입력을 파싱 할 수 없습니까? 예외적 일 수도 있고 그렇지 않을 수도 있습니다. 함수 자체는 일반적으로 알 수 없으며 어떤 컨텍스트에서 호출되는지 전혀 모릅니다.

그렇다면 특정 기능에 대해 예외를 사용해야하는지 여부를 어떻게 결정해야합니까? 실제로 일관된 유일한 방법은 모든 오류 처리에 사용하거나 아무것도 사용하지 않는 것 같습니다. 그리고 표준 라이브러리를 사용하고 있다면 그 선택이 저를 위해 만들어졌습니다.


6
FAQ 항목을 주의 깊게 읽어야합니다 . 이는 코딩 오류, 유효하지 않은 데이터, null 개체 참조 해제 또는 일반적인 런타임 불량과 관련된 모든 항목 에만 적용됩니다 . 일반적으로 어설 션은 절대 발생해서는 안되는 일을 식별하는 것입니다. 다른 모든 것에는 예외, 오류 코드 등이 있습니다.
Robert Harvey

1
@RobertHarvey는 정의에 여전히 동일한 문제가 있습니다. 사람의 개입없이 무언가를 해결할 수 있거나 프로그램의 상위 계층에만 알려지지 않은 경우.
cooky451

1
당신은 법학에 매달리고 있습니다. 장단점을 평가하고 자신의 마음을 구성하십시오. 또한, 귀하의 질문의 마지막 단락 ... 나는 그 자체를 전혀 고려하지 않습니다. 진실이 아마도 몇 가지 회색 음영에 더 가깝다면 당신의 생각은 매우 흑백입니다.
Robert Harvey

4
이 질문을하기 전에 조사를 시도 했습니까? C ++ 오류 처리 관용구는 웹에서 세부 사항을 설명하는 데 거의 확실하게 논의됩니다. 하나의 FAQ 항목에 대한 하나의 참조는 좋은 리서치가 아닙니다. 연구를 마친 후에도 여전히 자신의 마음을 구성해야합니다. 우리의 프로그래밍 학교가 어떻게 스스로 생각하는 방법을 모르는 마음이없는 소프트웨어 패턴 코딩 로봇을 만드는지에 대해 시작하지 마십시오.
Robert Harvey

2
그러한 규칙이 실제로 존재하지 않을 수도 있다는 나의 이론을 신뢰하는 것은 어느 것입니다. C ++ 라운지의 일부 사람들 귀하의 질문에 대답 할 수 있는지 확인하기 위해 초대했습니다 . 그러나 거기에 갈 때마다 "C ++ 사용을 중지하면 뇌가 튀어 나옵니다"라는 조언이 있습니다. 따라서 귀하의 책임은 귀하의 책임입니다.
Robert Harvey

답변:


15

첫째, 나는 std::exception그 아이들이 오래 전에 설계 되었다는 것을 지적해야한다고 생각 합니다. 오늘날 설계 될 경우 아마도 (거의 확실하게) 다를 수있는 많은 부분이 있습니다.

잘못 이해하지 마십시오 : 디자인에서 잘 작동하는 부분이 있으며 C ++의 예외 계층 구조를 디자인하는 방법에 대한 좋은 예입니다 (예 : 대부분의 다른 클래스와 달리 모두 클래스를 공유한다는 사실) 일반적인 뿌리).

구체적으로 살펴보면 logic_error약간의 수수께끼가 있습니다. 한편으로, 문제에 대한 합리적인 선택이 있다면 인용 한 조언이 옳습니다. 일반적 으로 가능한 빨리 빠르고 시끄럽게 실패하여 디버깅하고 수정할 수있는 것이 가장 좋습니다.

그러나 더 좋든 나쁘 든 일반적으로 해야 할 일에 대한 표준 라이브러리를 정의하기는 어렵습니다 . abort()잘못된 입력이 주어 졌을 때 프로그램을 종료하도록 (예를 들어, 호출하는 ) 이들을 정의했다면, 그 상황에서 항상 일어난 일이 될 것입니다. 적어도 배포 코드에서.

그것은 (적어도 약한) 실시간 요구 사항을 가진 코드에 적용되며, 부정확 한 출력에 대해서는 최소한의 페널티가됩니다. 예를 들어 채팅 프로그램을 생각해보십시오. 일부 음성 데이터를 디코딩하고 일부 잘못된 입력을 얻는 경우 사용자는 완전히 종료되는 프로그램보다 출력에서 ​​밀리 초의 정적을 유지하는 것이 훨씬 행복 할 수 있습니다. 마찬가지로 비디오 재생을 수행 할 때 입력 스트림이 손상되어 프로그램을 요약하여 종료하는 것보다 한 프레임 또는 두 프레임의 일부 픽셀에 대해 잘못된 값을 생성하는 것이 더 적합 할 수 있습니다.

특정 유형의 오류를보고하기 위해 예외를 사용할지 여부에 대해서는 다음과 같습니다. 사용 방법에 따라 동일한 작업이 예외로 간주 될 수 있습니다.

반면에 표준 라이브러리를 사용한다고해서 반드시 그 결정을 내려야하는 것은 아닙니다. 파일을 여는 경우 일반적으로 iostream을 사용합니다. Iostream은 정확히 최신이자 최고의 디자인은 아니지만이 경우 올바르게 작동합니다. 오류 모드를 설정하여 파일을 열지 못하는 경우 예외가 발생하는지 여부를 제어 할 수 있습니다. 따라서 응용 프로그램에 실제로 필요한 파일이 있고 파일 을 열지 못하면 심각한 치료 조치를 취해야한다는 의미이므로 해당 파일을 열지 못하면 예외가 발생할 수 있습니다. 존재하지 않거나 액세스 할 수없는 대부분의 파일에서 열려고하면 실패합니다 (이것이 기본값 임).

당신이 결정하는 방법에 관해서는 : 나는 쉬운 대답이 없다고 생각합니다. 더 나은지 나쁜지 "예외 상황"이 항상 측정하기 쉬운 것은 아닙니다. 결정하기 쉬운 사례는 반드시 예외적이어야하지만, 의문의 여지가 있거나 상황에 맞는 기능에 대한 지식이 필요한 경우가 있습니다. 그러한 경우, 사용자는 실패가 예외를 발생 시킬지 여부를 결정할 수있는 iostream의이 부분과 대략 비슷한 디자인을 고려할 가치가 있습니다. 또는 두 개의 개별 함수 세트 (또는 클래스 등)를 갖는 것이 가능합니다. 하나는 실패를 표시하기 위해 예외를 발생시키고 다른 하나는 다른 수단을 사용합니다. 그 길을 가면


9

std :: bitset 문자열 기반 생성자는 C ++ 11 이후에만 존재하므로 예외를 관용적으로 설계하여 설계해야합니다. 반면에 나는 사람들에게 logic_error가 기본적으로 전혀 사용되어서는 안된다고 말합니다.

당신은 이것을 믿을 수는 없지만, 다른 C ++ 코더들은 동의하지 않습니다. 그렇기 때문에 FAQ가 한 가지만 말하지만 표준 라이브러리는 동의하지 않습니다.

FAQ는 디버그가 더 쉬워 지므로 충돌을 옹호합니다. 충돌하여 코어 덤프를 받으면 응용 프로그램의 정확한 상태가됩니다. 예외를 던지면 그 상태를 많이 잃게됩니다.

표준 라이브러리는 코더에게 오류를 포착하고 처리 할 수있는 능력을 부여하는 것이 디버깅 가능성보다 더 중요하다는 이론을 취합니다.

예외적 일 수도 있고 그렇지 않을 수도 있습니다. 함수 자체는 일반적으로 알 수 없으며 어떤 컨텍스트에서 호출되는지 전혀 모릅니다.

여기서 아이디어는 상황이 예외적인지 여부를 함수가 알지 못하면 예외를 throw해서는 안된다는 것입니다. 다른 메커니즘을 통해 오류 상태를 반환해야합니다. 상태가 예외적임을 알고 프로그램의 특정 지점에 도달하면 예외를 처리해야합니다.

그러나 이것은 자체 문제가 있습니다. 함수에서 오류 상태가 반환 된 경우이를 확인해야하며 오류가 자동으로 전달됩니다. 이로 인해 어떤 사람들은 예외를 버리고 모든 종류의 오류 상태에 대해 예외를 던지는 예외적 인 규칙이 있습니다.

전반적으로 요점은 다른 사람들이 예외를 던질 때에 대해 다른 생각을 가지고 있다는 것입니다. 단 하나의 응집력있는 아이디어를 찾지 못할 것입니다. 어떤 사람들은 이것이 예외를 처리하는 올바른 방법이라고 독단적으로 주장 할지라도 이론에 대한 단일 합의는 없습니다.

예외를 던질 수 있습니다.

  1. 어디에나
  2. 프로그래머 오류에서만
  3. 절대 프로그래머가 아닌 오류
  4. 일상적이지 않은 (예외) 실패시에만

인터넷에서 귀하와 동의하는 사람을 찾으십시오. 자신에게 맞는 스타일을 채택해야합니다.


예외 상황이 정말 예외적 인 경우에만 예외를 사용하라는 제안은 예외의 성능이 좋지 않은 언어에 대해 가르치는 사람들이 널리 알리고 있다는 점에 주목할 가치가 있습니다. C ++은 그러한 언어 중 하나가 아닙니다.
Jules

1
@ 줄스-이제 (성능) 당신의 주장을 뒷받침 할 자신의 대답이 필요합니다. C ++ 예외 성능 확실히 문제이며 다른 곳보다 적을 수도 있지만 "C ++은 [예외가 나쁜 성능을 가진 언어] 중 하나가 아닙니다"라고 말할 수는 없습니다.
Martin Ba

1
@MartinBa-Java와 비교할 때 C ++ 예외 성능은 훨씬 빠릅니다. 벤치 마크에 따르면 예외를 1 수준으로 올리는 성능은 C ++에서 반환 값을 처리하는 것보다 약 50 배 느리고 Java에서는 1000 배 이상 느립니다. 이 경우 Java로 작성된 조언은 두 가지 사이의 성능 차이가 크기 때문에 별도의 생각없이 C ++에 적용해서는 안됩니다. 아마도 "성능 저조한"보다는 "매우 나쁜 성능"이라고 써야했을 것입니다.
Jules

1
@ Jules-이 숫자에 감사드립니다. (모든 소스?) 내가 할 수 자바 (그리고 C #) 필요 확실히 스택 추적을 캡처 할 수 있기 때문에, 그들을 믿는 정말 비싼 수 있었던 것처럼합니다. 나는 여전히 당신에게 초기 반응이 다소 오도라고 생각합니다 .50 배의 둔화조차도 상당히 무겁기 때문에 생각합니다. C ++와 같은 성능 지향 언어로
Martin Ba

2

다른 많은 좋은 답변이 작성되었습니다. 단지 추가하고 싶습니다.

전통적인 답변, 특히 ISO C ++ FAQ가 작성되었을 때 주로 "C ++ 예외"와 "C 스타일 리턴 코드"를 비교합니다. 세 번째 옵션 인 "일부 유형의 복합 값 (예 : a struct또는 union, 또는 요즘 boost::variant또는 (제안 된) 반환 ) std::expected은 고려되지 않습니다.

C ++ 11 이전에는 "복합 형식 반환"옵션이 일반적으로 매우 약했습니다. 왜냐하면 이동 의미론이 없었기 때문에 구조물 안팎으로 물건을 복사하는 것은 잠재적으로 매우 비쌌습니다. 최상의 성능을 얻으려면 RVO 에 맞게 코드를 스타일링하는 것이 언어의 시점에서 매우 중요했습니다 . 예외는 복합 유형을 효과적으로 반환하는 쉬운 방법과 같았습니다. 그렇지 않으면 상당히 어려울 것입니다.

C ++ 11 이후 IMO는 Result<T, E>요즘 Rust에서 사용되는 관용구와 유사한이 방법으로 "차별화 된 노조를 반환" 하는 것이 C ++ 코드에서 더 자주 선호되어야합니다. 때로는 오류를 나타내는 더 단순하고 편리한 스타일입니다. 예외적으로, 전에 던지지 않은 함수가 리팩토링 후에 갑자기 던지기 시작할 수있는 가능성이 항상 있으며 프로그래머는 항상 그런 것들을 잘 문서화하지는 않습니다. 오류가 식별 된 공용체에서 리턴 값의 일부로 표시되면 프로그래머가 C 코드 오류 처리에 대한 일반적인 비판 인 오류 코드를 무시할 가능성이 크게 줄어 듭니다.

일반적으로 Result<T, E>부스트 옵션처럼 작동합니다. operator bool값 또는 오류 인 경우을 사용하여 테스트 할 수 있습니다 . 그런 다음 say operator *를 사용하여 값 또는 다른 "get"함수에 액세스하십시오. 일반적으로 액세스 속도는 검사되지 않습니다. 그러나 디버그 빌드에서 액세스가 확인되고 어설 션이 실제로 값이 있고 오류가 아닌지 확인하도록 만들 수 있습니다. 이런 식으로 오류를 제대로 확인하지 않는 사람은 좀 더 교활한 문제보다는 단언 할 수 있습니다.

또 다른 이점은 잡히지 않는 예외와 달리이 스타일을 사용하여 스택을 임의의 거리로 날아 올리는 것입니다.이 스타일은 함수가 이전에 없었던 오류 신호를 시작할 때 처리하도록 코드가 변경되었습니다. 이로 인해 문제가 더 커집니다. "잡히지 않은 예외"라는 일반적인 문제는 런타임 오류보다 컴파일 타임 오류와 비슷해집니다.

나는이 스타일의 큰 팬이되었습니다. 일반적으로 요즘에는이 예외를 사용합니다. 그러나 예외를 주요 문제로 제한하려고합니다. 구문 분석 오류와 같은 경우 예 expected<T>를 들어 반환하려고 합니다. 상대적으로 사소한 문제 "문자열을 숫자로 변환 할 수 없습니다"의 경우 C ++ 예외 std::stoi와 같은 것들이 boost::lexical_cast발생하는 것은 요즘 나에게 맛이 좋지 않습니다.


1
std::expected여전히 받아 들일 수없는 제안입니까?
Martin Ba

당신 말이 맞아요, 아직 받아 들여지지 않은 것 같아요. 그러나 몇 가지 오픈 소스 구현이 떠 다니고 있다고 생각합니다. 가능한 상태가 두 개뿐이므로 변형 유형을 수행하는 것보다 덜 복잡합니다. 주요 디자인 고려 사항은 정확한 인터페이스가 무엇인지, 오류 객체가 실제로 있어야하는 Andrescu의 예상 <T>와 같기를 exception_ptr원하거나 구조 유형 또는 무언가를 사용하고 싶습니까? 그렇게
Chris Beck

Andrei Alexandrescu의 강연은 다음과 같습니다. channel9.msdn.com/Shows/Going+Deep/… 그는 이와 같은 클래스를 구성하는 방법과 고려해야 할 사항을 자세히 보여줍니다.
Chris Beck

제안 된 [[nodiscard]] attribute오류 처리 방법은 실수로 실수로 오류 결과를 무시하지 않기 때문에이 오류 처리 방법에 유용합니다.
코드 InChaos

네, AA의 대화를 알고있었습니다. 포장을 풀기 때문에 디자인이 꽤 이상하다는 것을 알았습니다 ( except_ptr) 내부에서 예외를 던져야했습니다. 개인적으로 나는 그러한 도구가 실행과 완전히 독립적으로 작동해야한다고 생각합니다. 단지 발언입니다.
Martin Ba

1

이것은 디자인의 일부이므로 매우 주관적인 문제입니다. 그리고 디자인은 기본적으로 예술이기 때문에 토론 대신 이러한 것들에 대해 논의하는 것을 선호합니다 (나는 당신이 토론하고 있다고 말하는 것이 아닙니다).

저에게는 예외적 인 사례는 두 가지 종류가 있습니다. 자원을 다루는 사례와 중요한 작업을 다루는 사례입니다. 중요하게 여겨 질 수있는 것은 현재의 문제와 많은 경우 프로그래머의 관점에 달려 있습니다.

자원을 얻지 못하면 예외를 던지는 가장 큰 후보입니다. 리소스는 메모리, 파일, 네트워크 연결 또는 문제 및 플랫폼을 기반으로하는 기타 요소 일 수 있습니다. 자, 자원을 공개하지 않으면 예외가 필요합니까? 글쎄, 그것은 다시 달려있다. 메모리 해제에 실패한 작업을 수행하지 않았으므로 해당 시나리오에 대해 잘 모르겠습니다. 그러나 자원 릴리스의 일부로 파일을 삭제하면 실패 할 수 있으며 실패했습니다.이 실패는 일반적으로 다중 프로세스 응용 프로그램에서 열린 상태로 유지 한 다른 프로세스와 관련이 있습니다. 파일과 마찬가지로 릴리스 중에 다른 리소스가 실패 할 수 있다고 생각하며 일반적 으로이 문제를 일으키는 디자인 결함이므로 예외를 던지는 것보다 수정하는 것이 좋습니다.

그런 다음 리소스를 업데이트합니다. 이 점은 적어도 응용 프로그램의 중요한 작업 측면과 밀접한 관련이 있습니다. 주어진 쉼표로 구분 된 문자열을 기반으로 세부 정보를 수정 Employee하는 함수 UpdateDetails(std::string&)가 있는 클래스를 상상해보십시오 . 메모리 해제 실패와 유사하게, 이러한 변수가 발생할 수있는 도메인에서의 경험 부족으로 인해 멤버 변수 값 할당이 실패한다고 상상하기 어렵다는 것을 알았습니다. 그러나 UpdateDetailsAndUpdateFile(std::string&)이름이 나타내는 것과 같은 기능 은 실패 할 것으로 예상됩니다. 이것이 내가 중요한 작업이라고 부르는 것입니다.

이제, 소위 크리티컬 오퍼레이션에 예외가 발생하는지 확인해야합니다. 내 말은, 소멸자와 마찬가지로 마지막에 발생하는 파일을 업데이트하고 있습니까? 아니면 매번 업데이트 한 후에 편집증 호출입니까? 쓰지 않은 개체를 정기적으로 쓰는 폴백 메커니즘이 있습니까? 내가 말하는 것은 작업의 중요도를 평가해야한다는 것입니다.

분명히 리소스와 관련이없는 중요한 작업이 많이 있습니다. 이 경우 UpdateDetails()잘못된 데이터가 주어집니다, 그것은 세부 사항을 업데이트하지 않습니다 당신은 여기에서 예외를 발생하도록 실패, 알려진해야합니다. 그러나 같은 기능을 상상해보십시오 GiveRaise(). 이제 직원이 뾰족한 머리 보스를 가지고 운이 좋으면 인상을 얻지 못할 경우 (프로그래밍 용어에서 일부 변수의 값으로 인해 발생하는 것을 막을 수 있음) 기능이 본질적으로 실패했습니다. 여기서 예외를 내시겠습니까? 내가 말하는 것은 예외의 필요성을 평가해야한다는 것입니다.

저에게는 일관성이 수업의 유용성보다 디자인 방식에 관한 것입니다. 내 말은 '모든 Get 함수는이 작업을 수행하고 모든 Update 함수는이 작업을 수행해야합니다'라는 관점에서 생각하지 않지만 특정 함수가 내 접근 방식의 특정 아이디어에 호소하는지 확인합니다. 표면적으로 클래스는 일종의 '유해성'으로 보일 수 있지만 사용자 (대부분 다른 팀의 동료)가 참여하거나 질문 할 때마다 설명하고 만족할 것 같습니다.

나는 C가 아닌 C ++을 사용하고 있기 때문에 기본적으로 반환 값을 예외로 대체하는 많은 사람들을 보았습니다. '오류 처리의 훌륭한 분리'등을 제공하고 '혼합'언어 등을 멈추도록 촉구합니다. 그런 사람들.


1

첫째, 다른 사람들이 언급했듯이 C ++에서는 IMHO 명확하게 잘리지 않습니다 .IMHO는 요구 사항과 제약 조건이 다른 언어보다 C ++에서 다소 다양하기 때문에 esp. "유사한"예외 문제가있는 C # 및 Java

std :: stof 예제를 공개하겠습니다.

빈 문자열을 std :: stof에 전달하면 프로그래밍 오류가 아닌 invalid_argument가 발생 함

기본 계약은 내가보기로,이 기능은 부동 소수점으로의 인수 변환을 시도하고 있다는 것입니다 어떤 이렇게하는 실패는 예외로보고됩니다. 두 가지 가능한 예외 는 모두 logic_error프로그래머 오류라는 의미가 아니라 "입력을 부동으로 변환 할 수 없다"는 의미에서 비롯된 것 입니다.

여기에서 logic_error(런타임) 입력이 주어지면 항상 변환하려고하면 오류가 있음을 나타내는 데 a 가 사용된다고 말할 수 있습니다.

참고 :이보기에서 a 는 함수에 동일한 입력이 주어지면 이론적으로 다른 실행에 성공할 runtime_error 있는 것으로 간주 될 수 있습니다. (예 : 파일 작업, DB 액세스 등)

추가 참고 : C ++ 정규식 라이브러리 여기와 동일하게 분류 될 수 있는 runtime_error경우가 있지만 오류가 발생 하도록 선택했습니다 (잘못된 정규식 패턴).

이것은 IMHO 가 C ++에서 그룹화 logic_하거나 runtime_오류가 퍼지 하고 일반적인 경우 (*)에서 실제로 큰 도움이되지 않는다는 것을 보여줍니다. 특정 오류를 처리 해야하는 경우 두 개보다 낮게 잡을 수 있습니다.

(*) : 즉 코드의 한 조각이 일치하지 않을 것을 말하는 것이 아니다, 그러나 당신은 던져 여부 runtime_logic_또는 custom_일도 중요한 것은, 내가 생각하지 정말이다.


stof와 둘 다에 대해 언급하려면 bitset:

두 함수 모두 문자열 을 인수로 사용하며 두 경우 모두 다음과 같습니다.

  • 주어진 문자열이 유효한지 여부를 호출자에게 확인하는 것은 사소한 일이 아닙니다 (예 : 최악의 경우 함수 논리를 복제해야합니다.
  • 문자열을 "파싱"하는 것은 이미 함수의 책임이므로 문자열을 이미 확인해야하므로 문자열을 균일하게 "사용"하는 오류를보고하는 것이 합리적입니다 (두 경우 모두 예외입니다). .

예외와 함께 자주 나타나는 규칙은 "예외 상황에서만 예외 사용"입니다. 그러나 라이브러리 함수는 어떤 상황이 예외적인지 어떻게 알 수 있습니까?

이 진술에는 IMHO의 두 가지 뿌리가 있습니다.

성능 : 중요한 경로에서 함수가 호출되고 "예외"사례가 예외적 이지 않은 경우, 즉 많은 양의 패스에는 예외가 발생하는 경우 예외 풀림 기계에 대해 매번 지불하는 것이 의미가 없습니다. 및 너무 느려.

에러 처리의 소재지 : 함수가 호출되고, 예외가 바로 잡아서 처리하면 에러 핸들링을 더 상세 바와 같이, 그 다음 예외 발생 작은 지점이 존재 catch 보다 if.

예:

float readOrDefault;
try {
  readOrDefault = stof(...);
} catch(std::exception&) {
  // discard execption, just use default value
  readOrDefault = 3.14f; // 3.14 is the default value if cannot be read
}

TryParsevs. 와 같은 함수가 작동하는 위치는 다음과 같습니다 Parse. 로컬 코드 가 구문 분석 된 문자열이 유효 할 것으로 예상 되는 버전 1 개, 로컬 코드가 실제로 구문 분석이 실패 할 것으로 예상되는 경우 (예 : 예외적이지 않은 버전) 버전 .

실제로, stof그냥 래퍼로 정의되어 strtof있으므로 예외를 원하지 않으면 해당 예외를 사용하십시오.


그렇다면 특정 기능에 대해 예외를 사용해야하는지 여부를 어떻게 결정해야합니까?

IMHO, 두 가지 경우가 있습니다 :

  • 함수와 같은 "라이브러리"(다른 상황에서 자주 재 사용됨) : 기본적으로 결정할 수 없습니다. 오류를보고하는 버전과 반환 된 오류를 예외로 변환하는 랩퍼 버전을 모두 제공 할 수 있습니다.

  • "응용 프로그램"기능 (응용 프로그램 코드의 얼룩에 따라 일부는 재사용 될 수 있지만 응용 프로그램 오류 처리 스타일 등에 의해 제한됨) 함수를 호출하는 코드 경로에서 예외없이 유용한 방법으로 예외를 처리하는 경우 예외를 사용하여 오류 를보고하십시오 (아래 참조) . 오류 리턴 스타일에 대해 응용 프로그램 코드를보다 쉽게 ​​읽고 쓸 수있는 경우이를 사용하십시오.

물론 그 사이에 장소가있을 것입니다. 필요한 것을 사용하고 YAGNI를 기억하십시오.


마지막으로 FAQ 문으로 돌아 가야한다고 생각합니다.

함수 사용시 코딩 오류를 나타 내기 위해 throw를 사용하지 마십시오. 프로세스를 디버거로 보내거나 프로세스를 중단하려면 assert 또는 기타 메커니즘을 사용하십시오.

나는 모든 오류이 가입 분명히 뭔가 심각하게 엉망이되어 있는지 또는 호출 코드가 있음을 표시 명확하게 그것이 무엇을하고 있었는지 몰랐다.

그러나 이 적절한 따라서 라이브러리 도메인 대 응용 프로그램 도메인 위 참조 종종 높은 응용 프로그램 고유의 것입니다.

이것은 호출 전제 조건 을 확인하는지 여부와 방법에 대한 질문으로 돌아 가지 만 이미 너무 오래 답변하지는 않습니다. :-)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.