Programing

귀환의 요점은 무엇입니까?

crosscheck 2020. 5. 23. 10:17
반응형

귀환의 요점은 무엇입니까?


[dcl.attr.noreturn] 은 다음 예제를 제공합니다.

[[ noreturn ]] void f() {
    throw "error";
    // OK
}

그러나 [[noreturn]]함수의 반환 유형이 이미 있기 때문에 요점을 이해하지 못합니다 void.

그렇다면 noreturn속성 의 요점은 무엇 입니까? 어떻게 사용해야합니까?


noreturn 속성은 호출자에게 반환되지 않는 함수에 사용됩니다. 즉, void 함수 (호출자에게 반환-값을 반환하지 않음)를 의미하는 것이 아니라 함수가 완료된 후 제어 흐름이 호출 함수로 반환되지 않는 함수 (예 : 응용 프로그램을 종료하는 함수, 영원히 반복하거나 예와 같이 예외를 throw하십시오).

이것은 컴파일러가 최적화를 수행하고 더 나은 경고를 생성하는 데 사용할 수 있습니다. 예를 들어 fnoreturn 속성이있는 경우 컴파일러는 g()쓸 때 데드 코드임을 경고 할 수 있습니다 f(); g();. 마찬가지로 컴파일러는에 대한 호출 후 누락 된 return 문에 대해 경고하지 않습니다 f().


noreturn컴파일러에게 함수가 값을 반환하지 않는다고 알려주지 않습니다. 컴파일러에게 제어 흐름이 호출자에게 반환되지 않음 을 알려줍니다 . 이를 통해 컴파일러는 다양한 최적화를 수행 할 수 있습니다. 호출 주변의 일시적인 상태를 저장 및 복원 할 필요가 없으며 호출을 따르는 코드를 데드 코딩하여 제거 할 수 있습니다.


기능이 완료되지 않았 음을 의미합니다. 다음에 대한 호출 후에 제어 흐름이 명령문에 절대로 도달하지 않습니다 f().

void g() {
   f();
   // unreachable:
   std::cout << "No! That's impossible" << std::endl;
}

정보는 컴파일러 / 최적화 프로그램이 다른 방식으로 사용할 수 있습니다. 컴파일러는 위의 코드에 도달 할 수 없다는 경고를 추가 할 수 있으며 g()연속성을 지원하기 위해 다양한 방법으로 실제 코드를 수정할 수 있습니다 .


이전 답변은 귀환이 무엇인지 정확하게 설명했지만 존재 이유 는 아닙니다 . 나는 "최적화"주석이 주된 목적이라고 생각하지 않습니다. 반환하지 않는 함수는 드물고 보통 최적화 할 필요가 없습니다. 오히려 나는 귀환의 주요 원인은 거짓 양성 경고를 피하는 것이라고 생각합니다. 예를 들어 다음 코드를 고려하십시오.

int f(bool b){
    if (b) {
        return 7;
    } else {
        abort();
    }
 }

abort ()가 "noreturn"으로 표시되지 않은 경우 컴파일러는 f가 예상대로 정수를 리턴하지 않는 경로를 갖는이 코드에 대해 경고했을 수 있습니다. 그러나 abort ()는 반환되지 않기 때문에 코드가 정확하다는 것을 알고 있습니다.


이론적으로 말하면, void다른 언어 unit또는 로 불리는 것입니다 top. 논리적으로 동등한 것은 True 입니다. 모든 값은 합법적으로 캐스트 될 수 있습니다 void(모든 유형은의 하위 유형입니다 void). "우주"세트로 생각하십시오. 세계의 모든에 공통된 연산 이 없으므로 type 값에 유효한 연산이 없습니다 void. 다른 방식으로 말하면, 어떤 것이 우주 세트에 속한다고 말하면 어떤 정보도 제공하지 않습니다. 이미 알고 있습니다. 따라서 다음은 소리입니다.

(void)5;
(void)foo(17); // whatever foo(17) does

그러나 아래 과제는 그렇지 않습니다.

void raise();
void f(int y) {
    int x = y!=0 ? 100/y : raise(); // raise() returns void, so what should x be?
    cout << x << endl;
}

[[noreturn]]반면에, 때로는라고 empty, Nothing, Bottom또는 Bot과의 논리와 동일 거짓 . 값이 전혀 없으며이 유형의 표현식은 모든 유형으로 캐스트 될 수 있습니다 (예 : 하위 유형). 이것은 빈 세트입니다. 누군가가 "foo () 표현식의 값이 빈 세트에 속한다" 말하면 정보 매우 유익합니다.이 표현식은 정상적인 실행을 완료하지 못할 것입니다. 중단, 던지거나 매달려 있습니다. 와 정반대입니다 void.

따라서 다음은 의미가 없습니다 (의사 C ++, noreturn일류 C ++ 유형이 아니기 때문에 )

void foo();
(noreturn)5; // obviously a lie; the expression 5 does "return"
(noreturn)foo(); // foo() returns void, and therefore returns

그러나 아래의 할당 throw은 컴파일러가 반환하지 않는 것으로 이해 되기 때문에 완벽하게 합법적입니다 .

void f(int y) {
    int x = y!=0 ? 100/y : throw exception();
    cout << x << endl;
}

In a perfect world, you could use noreturn as the return value for the function raise() above:

noreturn raise() { throw exception(); }
...
int x = y!=0 ? 100/y : raise();

Sadly C++ does not allow it, probably for practical reasons. Instead it gives you the ability to use [[ noreturn ]] attribute which helps guiding compiler optimizations and warnings.

참고URL : https://stackoverflow.com/questions/10538291/what-is-the-point-of-noreturn

반응형