언제 실제로 noexcept를 사용해야합니까?


507

noexcept키워드는 많은 함수 시그니처에 적절하게 적용될 수 있지만 실제로 키워드를 언제 사용해야하는지 잘 모르겠습니다. 지금까지 읽은 내용을 기반으로 마지막 순간 추가는 noexcept이동 생성자가 던질 때 발생하는 몇 가지 중요한 문제를 해결하는 것으로 보입니다. 그러나 여전히 실용적인 질문에 대한 만족스러운 답변을 제공 할 수 없어서 noexcept처음부터 더 자세히 읽을 수 있었습니다.

  1. 필자가 결코 알지 못할 함수의 많은 예가 있지만 컴파일러가 스스로 결정할 수는 없습니다. 그러한 모든 경우noexcept 에 함수 선언에 추가해야합니까 ?

    모든 함수 선언 noexcept후에 추가해야하는지에 대해 생각해야하는 것은 프로그래머의 생산성을 크게 떨어 뜨릴 것입니다. 어떤 상황에서 사용에 대해 더주의를 기울여야하며 , 어떤 상황에서 묵시적으로 벗어날 수 있습니까?noexceptnoexcept(false)

  2. 언제 사용 후 성능 향상을 실제로 볼 수 noexcept있습니까? 특히, C ++ 컴파일러가를 추가 한 후 더 나은 기계 코드를 생성 할 수있는 코드의 예를 제공하십시오 noexcept.

    개인적으로, noexcept특정 종류의 최적화를 안전하게 적용하기 위해 컴파일러에 제공되는 자유가 증가했기 때문에 관심이 있습니다. 최신 컴파일러 noexcept는 이런 방식으로 활용 합니까? 그렇지 않다면, 그들 중 일부는 가까운 시일 내에 그렇게 할 것으로 기대할 수 있습니까?


40
move_if_nothrownoccept 이동 ctor가있는 경우 (또는 whatchamacallit) 코드를 사용 하면 성능이 향상됩니다.
R. Martinho Fernandes


5
그것은이다 move_if_noexcept.
Nikos

답변:


180

실제로 사용하기에 충분한 시간이 없었기 때문에 "모범 사례"에 대한 답변을하기에는 너무 이르다고 생각합니다. 이것이 던져진 직후 던져 지정자에 대해 묻는다면 그 대답은 지금과 매우 다릅니다.

noexcept모든 함수 선언 후에 추가해야하는지에 대해 생각해야 한다면 프로그래머의 생산성이 크게 떨어질 것입니다 (솔직히 고통 스럽습니다).

그렇다면 함수가 절대로 throw되지 않는 것이 분명 할 때 사용하십시오.

언제 사용 후 성능 향상을 실제로 볼 수 noexcept있습니까? 개인적으로, 나는 noexcept특정 종류의 최적화를 안전하게 적용하기 위해 컴파일러에 제공되는 자유가 증가했기 때문에 신경 을 쓴다.

확인 noexcept및 과부하 가능성으로 인해 컴파일러 최적화가 아닌 사용자 최적화에서 가장 큰 최적화 이점을 얻는 것 같습니다 . 대부분의 컴파일러는 페널티가없는 경우 예외 처리 방법을 따르지 않으므로 코드의 기계 코드 수준에서 많은 (또는 무엇이든) 변경 될지 의심 스럽습니다. 취급 코드.

사용 noexcept빅 4에 (이미있는 한 생성자, 할당되지 소멸자 noexcept로 가능성이 가장 개선의 원인이됩니다) noexcept검사는 같이 템플릿 코드에서 '일반'이다 std용기. 예를 들어, std::vector클래스가 표시되어 있지 않으면 클래스의 이동을 사용하지 않습니다 noexcept(또는 컴파일러가 다른 방법으로 추론 할 수 있음).


6
나는 그 std::terminate트릭이 여전히 Zero-Cost 모델을 따른 다고 생각한다 . 즉, noexcept함수 내의 명령어 범위가 스택 언 와인 더 대신 사용되는 std::terminate경우 호출에 매핑됩니다 throw. 따라서 정기적 인 예외 추적보다 더 많은 오버 헤드가 의심됩니다.
Matthieu M.

4
@Klaim 이것을보십시오 : stackoverflow.com/a/10128180/964135 실제로는 던지지 않아야하지만 noexcept이것을 보장합니다.
Pubby

3
" noexcept함수가 std::terminate오버 헤드가 적은 것처럼 보이는 함수 가 호출되면"… 아니오, 이는 예외 디스패처가 포착 한 후 구제되어야하는 해당 함수에 대한 예외 테이블을 생성하지 않고 구현되어야합니다.
Potatoswatter

8
@Pubby C ++ 예외 처리는 일반적으로 호출 사이트 주소를 처리기 시작점에 던질 수있는 점프 테이블을 제외하고 오버 헤드없이 수행됩니다. 이러한 테이블을 제거하면 예외 처리를 완전히 제거 할 수 있습니다. 유일한 차이점은 실행 파일 크기입니다. 아마도 아무것도 언급 할 가치가 없습니다.
Potatoswatter

26
"그런 다음 함수가 절대 던져지지 않을 것이 확실 할 때 사용하십시오." 동의하지 않습니다. noexcept함수 인터페이스 의 일부입니다 . 현재 구현이 발생하지 않기 때문에 추가해서는 안됩니다 . 이 질문에 대한 정답은 확실하지 않지만, 오늘날 귀하의 기능이 어떻게 작동하는지는 그 기능과 아무런 관련이 없다고 확신합니다.
Nemo

133

요즘 계속 반복하면서 의미론이 먼저 .

추가 noexcept, noexcept(true)그리고 것은 noexcept(false)무엇보다도 의미에 대한 것입니다. 우연히 많은 가능한 최적화를 조건화합니다.

프로그래머가 코드를 읽는 것처럼 존재하는 noexcept것과 비슷합니다 const. 발생하거나 발생하지 않는 것을 더 잘 이해하는 데 도움이됩니다. 따라서 함수가 발생할지 여부를 생각하는 데 시간을 투자하는 것이 좋습니다. 다시 말해, 모든 종류의 동적 메모리 할당이 발생할 수 있습니다.


이제 가능한 최적화로 넘어갑니다.

가장 확실한 최적화는 실제로 라이브러리에서 수행됩니다. C ++ 11은 함수의 유무를 알 수있는 여러 가지 특성을 제공하며 noexcept표준 라이브러리 구현 자체는 해당 특성을 사용하여 noexcept가능한 경우 조작하는 사용자 정의 오브젝트에 대한 조작 을 선호 합니다. 이동 의미 와 같은 .

이 때문에 컴파일러는 데이터에만 예외 처리에서 지방 (아마)의 비트를 면도 할 수 있다 계정으로 당신이 거짓말을 할 수 있다는 사실을 고려 할 수 있습니다. 표시된 함수 noexcept가 throw되면 std::terminate호출됩니다.

이 의미론은 다음 두 가지 이유로 선택되었습니다.

  • noexcept종속성이 아직 사용하지 않는 경우에도 즉시 혜택 (역 호환성)
  • noexcept이론적으로 던질 수 있지만 주어진 인수에 대해 예상되지 않는 함수를 호출 할 때 의 스펙을 허용

2
어쩌면 나는 순진하지만 함수 만 호출하는 noexcept함수는 특별한 일을 할 필요가 없다고 상상할 것입니다. 예외가 발생 terminate하기 전에 발생할 수있는 예외는 이 수준에 도달하기 때문입니다. 이는 bad_alloc예외 를 처리하고 전파해야하는 것과 크게 다릅니다 .

8
예, 제안한 방식으로 noexcept를 정의 할 수 있지만 실제로는 사용할 수없는 기능입니다. 특정 조건이 유지되지 않으면 많은 함수가 throw 될 수 있으며 조건이 충족되었다는 것을 알더라도 호출 할 수 없습니다. 예를 들어 std :: invalid_argument를 던질 수있는 함수입니다.
tr3w

3
@MatthieuM. 답장은 조금 늦었지만 그럼에도 불구하고 noexcept로 표시된 함수는 던질 수있는 다른 함수를 호출 할 수 있습니다.이 함수는 예외를 발생시키지 않습니다. 즉, 예외 자체를 처리해야합니다.
Hond December

4
나는이 답변을 오래 전에 찬성했지만 더 자세히 읽고 생각하면 의견 / 질문이 있습니다. "시맨틱 이동"은 내가 분명히 도움이되고 / 좋은 생각을하는 사람이 본 것을 본 유일한noexcept입니다. 이동 구성, 이동 할당 및 스왑이 유일한 경우라고 생각하기 시작했습니다. 다른 사람을 알고 있습니까?
니모

5
@Nemo : 표준 라이브러리에서는 이것이 유일한 라이브러리 일 수 있지만 다른 곳에서 재사용 할 수있는 원리를 보여줍니다. 이동 작업은 일부 상태를 "림보"로 일시적으로 설정하는 작업으로, noexcept나중에 액세스 할 수있는 데이터에 누군가가 자신있게 사용할 수있는 경우에만 가능합니다. 이 아이디어가 다른 곳에서 사용되는 것을 볼 수는 있지만 표준 라이브러리는 C ++에서 다소 얇으며 생각하는 요소의 사본을 최적화하는 데만 사용됩니다.
Matthieu M.

77

이것은 실제로 컴파일러의 옵티 마이저와 (잠재적으로) 큰 차이를 만듭니다. 컴파일러는 실제로 함수 확장 이후의 빈 throw () 문과 속성 확장을 통해이 기능을 몇 년 동안 가지고있었습니다. 최신 컴파일러가이 지식을 활용하여 더 나은 코드를 생성한다는 것을 확신 할 수 있습니다.

컴파일러의 거의 모든 최적화는 합법적 인 것에 대해 추론하기 위해 함수의 "흐름 그래프"라는 것을 사용합니다. 플로우 그래프는 일반적으로 함수의 "블록"이라고하는 것 (단일 입구와 단일 출구가있는 코드 영역)과 플로우가 이동할 수있는 위치를 나타내는 블록 사이의 에지로 구성됩니다. Noexcept는 플로우 그래프를 변경합니다.

구체적인 예를 요청했습니다. 이 코드를 고려하십시오.

void foo(int x) {
    try {
        bar();
        x = 5;
        // Other stuff which doesn't modify x, but might throw
    } catch(...) {
        // Don't modify x
    }

    baz(x); // Or other statement using x
}

이 함수에 대한 플로우 그래프 bar는 레이블이 지정된 경우 다릅니다 noexcept(실행 bar문 끝 과 catch 문 사이를 이동할 수있는 방법이 없습니다 ). 로 레이블이 지정되면 noexcept컴파일러는 baz 함수 중 x의 값이 5임을 확신합니다. x = 5 블록은 bar()catch 문 에서 가장자리없이 baz (x) 블록을 "지배"한다고 합니다.

그런 다음보다 일정한 코드를 생성하기 위해 "일정한 전파"라는 것을 수행 할 수 있습니다. 여기서 baz가 인라인되면 x를 사용하는 명령문에도 상수가 포함될 수 있으며 런타임 평가에 사용되었던 것을 컴파일 타임 평가 등으로 바꿀 수 있습니다.

어쨌든, 짧은 대답 : noexcept컴파일러가 더 엄격한 흐름 그래프를 생성하게하고 흐름 그래프는 모든 종류의 일반적인 컴파일러 최적화에 대해 추론하는 데 사용됩니다. 컴파일러에게는 이러한 특성의 사용자 주석이 훌륭합니다. 컴파일러는이 물건을 알아 내려고 시도하지만 일반적으로 할 수 없습니다 (문제의 함수는 컴파일러에 보이지 않는 다른 객체 파일에 있거나 보이지 않는 일부 함수를 전 이적으로 사용할 수 있습니다). 당신이 알지도 못했을 수도있는 사소한 예외가 있으므로 암시 적으로 레이블을 지정할 수 없습니다 noexcept(예 : 할당 메모리는 bad_alloc을 던질 수 있음).


3
실제로 실제로 차이가 있습니까? 전에는 아무것도x = 5 던질 수 없기 때문에 예제가 고안되었습니다 . try블록 의 해당 부분이 어떤 목적으로 사용된다면 추론은 유지되지 않을 것입니다.
Potatoswatter

7
try / catch 블록을 포함하는 함수를 최적화하는 데 실제로 차이가 있다고 말하고 싶습니다. 내가 생각했지만 제시 한 예는 완전하지 않습니다. 더 큰 요점은 noexcept (이전의 throw () 문과 같은)는 컴파일이 더 작은 흐름 그래프 (가장자리가 적고 블록이 적음)를 생성하는 데 도움이되며, 이는 많은 최적화의 기본 부분입니다.
Terry Mahaffey

컴파일러가 코드에서 예외를 발생시킬 수 있음을 어떻게 인식 할 수 있습니까? 배열에 대한 액세스가 가능한 예외로 간주됩니까?
Tomas Kubes

3
@ qub1n 컴파일러가 함수의 본문을 볼 수있는 경우 명시적인 throw명령문을 찾거나 이와 유사한 다른 항목 new을 찾을 수 있습니다. 컴파일러가 본문을 볼 수 없으면의 존재 여부에 의존해야합니다 noexcept. 일반 배열 액세스는 일반적으로 예외를 생성하지 않으므로 (C ++에는 범위 검사가 없음) 아니요, 배열 액세스만으로 컴파일러가 함수가 예외를 throw한다고 생각하지는 않습니다. (아웃 바운드 액세스는 보장 된 예외가 아닌 UB입니다.)
cdhowie

@cdhowie는 "noexcept 의 유무에 의존해야한다 "또는 throw()pre-noexcept C ++에 존재해야한다
curiousguy

57

noexcept일부 작업의 성능을 크게 향상시킬 수 있습니다. 컴파일러에서 머신 코드를 생성하는 수준에서는 발생하지 않지만 가장 효과적인 알고리즘을 선택하면됩니다. 다른 언급했듯이 function을 사용하여이 선택을 수행 std::move_if_noexcept합니다. 예를 들어 std::vector(예 : 전화 할 때) 의 증가 reserve는 강력한 예외 안전 보장을 제공해야합니다. T의 이동 생성자가 던지지 않는다는 것을 알고 있다면 모든 요소를 ​​이동할 수 있습니다. 그렇지 않으면 모든 Ts 를 복사해야합니다 . 이에 대해서는 이 게시물 에서 자세히 설명했습니다 .


4
부록 : 이는 이동 생성자를 정의하거나 이동 할당 연산자를 추가 noexcept하는 경우 해당되는 경우를 의미합니다! 암시 적으로 정의 된 이동 멤버 기능이 noexcept자동으로 추가되었습니다 (해당되는 경우).
mucaho

33

사용 후 성능 향상을 관찰하는 것 외에는 현실적으로 언제 할 수 noexcept있습니까? 특히, noexcept를 추가 한 후 C ++ 컴파일러가 더 나은 기계 코드를 생성 할 수있는 코드의 예를 제공하십시오.

음, 절대? 시간이 없습니까? 못.

noexcept을위한 컴파일러 같은 방법으로 성능 최적화 const컴파일러 성능 최적화를위한 것입니다. 즉, 거의 없습니다.

noexcept함수가 예외를 던질 수있는 경우 컴파일 타임에 "사용자"가 감지 할 수 있도록하는 데 주로 사용됩니다. 기억하십시오 : 대부분의 컴파일러는 실제로 무언가를 던지지 않는 한 예외에 대한 특수 코드를 생성하지 않습니다. 그래서 noexcept함수를 최적화하는 방법에 대한 컴파일러 힌트를주는 너무 많이로 제공의 문제가 아니라 당신이 함수를 사용하는 방법에 대한 힌트.

같은 템플릿 move_if_noexcept은 이동 생성자가 정의되어 있는지 감지하고 그렇지 않은 경우 유형 대신 대신을 noexcept반환합니다 . 그렇게하는 것이 매우 안전하다면 움직이라는 말입니다.const&&&

일반적으로 noexcept실제로 유용한 것으로 생각 될 때 사용해야합니다 . is_nothrow_constructible해당 유형에 해당하는 경우 일부 코드는 다른 경로 를 사용합니다. 그렇게하는 코드를 사용하는 경우 noexcept적절한 생성자를 자유롭게 사용하십시오 .

한마디로 : 이동 생성자와 유사한 구성에 사용하십시오. 그러나 그 구성 요소에 신경 쓸 필요는 없습니다.


13
엄밀히 말하면 move_if_noexcept복사본을 반환하지 않고 rvalue-reference가 아닌 const lvalue-reference를 반환합니다. 일반적으로 호출자가 이동 대신 복사를하지만 move_if_noexcept복사를 수행하지 않습니다. 그렇지 않으면 좋은 설명입니다.
Jonathan Wakely

12
+1 조나단. 예를 들어 벡터 크기를 조정하면 이동 생성자가 인 경우 객체를 복사하지 않고 이동합니다 noexcept. "never"는 사실이 아닙니다.
mfontanini

4
컴파일러 그 상황에서 더 나은 코드를 생성 할 것 입니다. OP는 컴파일러가보다 최적화 된 응용 프로그램을 생성 할 수있는 예를 요구하고 있습니다. 컴파일러 최적화가 아니더라도 마찬가지 입니다.
mfontanini

7
@mfontanini : 컴파일러는 다른 코드 경로를 강제로 컴파일하기 때문에 더 나은 코드 만 생성 합니다. 그것은 단지 때문에 작동 std::vector컴파일하도록 컴파일러에 강제로 기록되는 다른 코드를. 컴파일러가 무언가를 감지하는 것이 아닙니다. 사용자 코드가 무언가를 감지하는 것입니다.
Nicol Bolas

3
문제는 대답의 시작 부분에서 인용 부호에서 "컴파일러 최적화"를 찾을 수없는 것입니다. @ChristianRau가 말했듯이 컴파일러는보다 효율적인 코드를 생성하므로 최적화의 기원은 중요하지 않습니다. 결국 컴파일러 보다 효율적인 코드를 생성하고 있습니까? 추신 : 나는 그것이 컴파일러 최적화라고 말한 적이 없으며 심지어 "컴파일러 최적화가 아닙니다"라고 말했습니다.
mfontanini

22

에서 비얀 의 단어 ( 는 C ++의 언어, 제 4 판 프로그래밍 , 페이지 366)

종료가 수용 가능한 응답 인 경우 종료되지 않은 예외는 terminate () 호출 (§13.5.2.5)이되기 때문에이를 달성 할 수 있습니다. 또한 noexcept지정자 (§13.5.1.1)는 그러한 요구를 명시 적으로 만들 수 있습니다.

성공적인 내결함성 시스템은 다단계입니다. 각 수준은 너무 왜곡되지 않고 가능한 많은 오류를 처리하고 나머지는 더 높은 수준으로 둡니다. 예외는 그 관점을 지원합니다. 또한 terminate()예외 처리 메커니즘 자체가 손상 되었거나 불완전하게 사용 된 경우 이스케이프를 제공하여이보기를 지원 하므로 예외가 포착되지 않습니다. 마찬가지로, noexcept복구하려고 시도 할 수없는 오류에 대한 간단한 탈출을 제공합니다.

double compute(double x) noexcept;     {
    string s = "Courtney and Anya";
    vector<double> tmp(10);
    // ...
}

벡터 생성자는 10 더블에 대한 메모리를 확보하지 못하고를 던질 수 std::bad_alloc있습니다. 이 경우 프로그램이 종료됩니다. 호출하면 무조건 종료됩니다 std::terminate()(§30.4.1.3). 소멸자가 함수 호출을 호출하지 않습니다. throw와 사이의 범위에서 소멸자 noexcept가 호출 되는지 여부는 구현 정의입니다 (예 : compute ()의 경우). 프로그램은 곧 종료 될 것이므로 어떤 객체에도 의존해서는 안됩니다. 지정자 를 추가함으로써 noexcept, 우리는 코드가 드로우에 대처하도록 작성되지 않았 음을 나타냅니다.


2
이 견적의 출처가 있습니까?
Anton Golov

5
@AntonGolov "C ++ 프로그래밍 언어, 제 4 판"pg. 366
Rusty Shackleford

noexcept명시 적으로 예외를 처리하려는 경우를 제외하고 는 실제로 매번 추가 해야하는 것처럼 들립니다 . 현실적으로 말하면, 대부분의 예외는 너무나 불가능하고 치명적이어서 구조가 거의 합리적이거나 불가능합니다. 예를 들어 인용 된 예에서 할당이 실패하면 응용 프로그램이 계속 올바르게 작동하지 않습니다.
Neonit

21
  1. 필자가 결코 알지 못할 함수의 많은 예가 있지만 컴파일러가 스스로 결정할 수는 없습니다. 그러한 모든 경우에 함수 선언에 noexcept를 추가해야합니까?

noexcept함수 인터페이스의 일부이므로 까다 롭습니다. 특히 라이브러리를 작성하는 경우 클라이언트 코드가 noexcept속성에 따라 달라질 수 있습니다 . 기존 코드가 손상 될 수 있으므로 나중에 변경하기 어려울 수 있습니다. 응용 프로그램에서만 사용하는 코드를 구현할 때는 걱정할 필요가 없습니다.

던질 수없는 함수가 있다면, 유지를 원하는지 noexcept또는 향후 구현을 제한 할 것인지 스스로에게 물어보십시오 . 예를 들어 예외 (예 : 단위 테스트)를 발생시켜 잘못된 인수에 대한 오류 검사를 수행하거나 예외 사양을 변경할 수있는 다른 라이브러리 코드에 의존 할 수 있습니다. 이 경우 보수적이고 생략하는 것이 더 안전합니다 noexcept.

반면에, 함수가 절대로 던져지지 않아야하고 그것이 사양의 일부인 것이 정확하다고 확신하는 경우이를 선언해야합니다 noexcept. 그러나 noexcept구현이 변경 될 경우 컴파일러는 위반을 감지 할 수 없습니다 .

  1. 어떤 상황에서 noexcept의 사용에 대해 더주의를 기울여야하며, 어떤 상황에서 묵시적인 noexcept (false)로 벗어날 수 있습니까?

가장 큰 영향을 미치기 때문에 집중해야 할 네 가지 기능 클래스가 있습니다.

  1. 이동 작업 (할당 연산자 이동 및 생성자 이동)
  2. 스왑 작업
  3. 메모리 할당 해제 기 (운영자 삭제, 운영자 삭제 [])
  4. 소멸자 ( noexcept(true)당신이 그들을 만들지 않는 한 이것들은 암시 적으로 있지만 noexcept(false))

이러한 함수는 일반적으로이어야 noexcept하며 라이브러리 구현 noexcept에서이 속성 을 사용할 수 있습니다 . 예를 들어, std::vector강력한 예외 보장을 희생하지 않고 비 투척 이동 작업을 사용할 수 있습니다. 그렇지 않으면 (C ++ 98에서와 같이) 복사 요소로 폴백해야합니다.

이러한 종류의 최적화는 알고리즘 수준에 있으며 컴파일러 최적화에 의존하지 않습니다. 특히 요소를 복사하는 데 비용이 많이 드는 경우 큰 영향을 줄 수 있습니다.

  1. noexcept를 사용한 후 성능 향상을 현실적으로 볼 수있는 시점은 언제입니까? 특히, noexcept를 추가 한 후 C ++ 컴파일러가 더 나은 기계 코드를 생성 할 수있는 코드의 예를 제공하십시오.

noexcept예외 사양을 사용하지 않거나 throw()스택을 풀 때 표준에 따라 컴파일러에서 더 많은 자유를 얻을 수 있다는 이점이 있습니다. 이 throw()경우 에도 컴파일러는 스택을 완전히 풀어야합니다 (그리고 객체 구성의 정확한 역순으로해야합니다).

에서 noexcept경우에, 다른 한편으로는 그렇게 할 필요가 없습니다. 스택을 풀어야 할 필요는 없습니다 (그러나 컴파일러는 여전히 그렇게 할 수 있습니다). 이러한 자유로 인해 스택을 항상 풀 수있는 오버 헤드가 줄어들 기 때문에 코드 최적화가 더욱 강화됩니다.

noexcept, 스택 해제 및 성능 에 대한 관련 질문은 스택 해제가 필요한 경우 오버 헤드에 대한 자세한 정보를 제공합니다.

자세한 내용은 Scott Meyers의 "Effective Modern C ++"책, "항목 14 : 예외가 발생하지 않는 경우를 제외하고 함수 선언"을 참조하십시오.


Java와 같이 C ++에서 예외가 구현 된 경우 throws키워드 대신 noexcept제외 키워드 를 표시 할 수있는 예외를 표시하는 것이 훨씬 더 의미가 있습니다 . C ++ 디자인 선택 사항을 얻을 수 없습니다 ...
doc

그들은 이미 찍은 noexcept때문에 그것을 명명했습니다 throw. 간단히 말하면 거의 쓸모가 없어서 쓸모 없게 된 디자인을 제외하고는 언급 한 거의 그대로 throw사용할 수 있습니다 . 그러나 우리는 그것을 제거하면 거의 이익이되지 않는 주요 변경 사항이 될 것이기 때문에 지금 붙어 있습니다. 그래서 기본적으로 . noexceptthrow_v2
AnorZaken

어떻게 throw유용하지 않습니까?
curiousguy

@curiousguy "throw"자체 (예외 던지기)는 유용하지만 예외 지정자로 "throw"는 더 이상 사용되지 않으며 C ++ 17에서도 제거되었습니다. 예외 지정자가 유용하지 않은 이유는 다음 질문을 참조하십시오. stackoverflow.com/questions/88573/…
Philipp Claßen

1
@ PhilippClaßen throw()예외 지정 자는 nothrow?
curiousguy

17

필자가 결코 알지 못할 함수의 많은 예가 있지만 컴파일러가 스스로 결정할 수는 없습니다. 그러한 모든 경우에 함수 선언에 noexcept를 추가해야합니까?

"[그들은 결코 던질 수 없다는 것을 안다"라고 말할 때, 당신은 함수가 던지지 않을 것이라는 것을 알고있는 함수의 구현을 검사한다는 것을 의미합니다. 나는 그 접근 방식이 외부에 있다고 생각합니다.

함수가 함수 디자인 의 일부로 예외를 발생시킬 수 있는지 여부를 고려하는 것이 좋습니다 . 인수 목록만큼 중요하고 메소드가 변경자인지 여부 (... const)입니다. "이 함수는 예외를 던지지 않는다"고 선언하는 것은 구현에 제약이된다. 그것을 생략한다고해서 함수가 예외를 throw하는 것은 아닙니다. 이는 현재 버전의 함수 모든 향후 버전에서 예외가 발생할 수 있음을 의미합니다 . 구현을 더 어렵게 만드는 것은 제약입니다. 그러나 일부 방법에는 실제로 유용한 제약 조건이 있어야합니다. 가장 중요한 점은 소멸자로부터 호출 할 수 있지만 강력한 예외 보장을 제공하는 메소드에서 "롤백"코드를 구현하는 것입니다.


이것이 가장 좋은 답변입니다. 당신은 메소드의 사용자에게 보증을하고 있습니다. 이것은 구현을 영원히 제한한다고 말하는 또 다른 방법입니다 . 깨달은 관점에 감사드립니다.
AnorZaken

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