예외 사양(throw, noexcept)(C++)
예외 사양은 함수에서 전파할 수 있는 예외 형식에 대한 프로그래머의 의도를 나타내는 C++ 언어 기능입니다. 예외 사양을 사용하여 함수가 예외에 의해 종료되거나 종료되지 않도록 지정할 수 있습니다. 컴파일러는 이 정보를 사용하여 함수에 대한 호출을 최적화하고, 예기치 않은 예외가 함수를 이스케이프하는 경우 프로그램을 종료할 수 있습니다.
C++17 이전에는 두 가지 종류의 예외 사양이 있었습니다. Noexcept 사양은 C++11에서 새로 추가되었습니다. 함수를 이스케이프할 수 있는 잠재적 예외 집합이 비어 있는지 여부를 지정합니다. 동적 예외 사양 또는 사양은 C++11에서 더 이상 사용되지 않으며, 별칭noexcept(true)
인 경우를 제외하고 throw()
C++17 throw(optional_type_list)
에서 제거되었습니다. 이 예외 사양은 함수에서 throw될 수 있는 예외에 대한 요약 정보를 제공하도록 설계되었지만 실제로는 문제가 있는 것으로 밝혀졌습니다. 다소 유용한 것으로 입증된 동적 예외 사양 중 하나는 무조건 throw()
적인 사양이었습니다. 예를 들어 함수 선언은 다음과 같습니다.
void MyFunction(int i) throw();
컴파일러에 함수가 아무 예외도 throw하지 않음을 알립니다. 그러나 함수가 예외를 throw하는 경우 모드에서 /std:c++14
정의되지 않은 동작이 발생할 수 있습니다. 따라서 위의 연산자 noexcept
대신 연산자를 사용하는 것이 좋습니다.
void MyFunction(int i) noexcept;
다음 표에서는 예외 사양의 Microsoft C++ 구현을 요약합니다.
예외 사양 | 의미 |
---|---|
noexcept noexcept(true) throw() |
이 함수는 예외를 throw하지 않습니다. /std:c++14 모드(기본값) noexcept 와 noexcept(true) 동일합니다. 선언되거나 호출되는 noexcept noexcept(true) std::terminate 함수에서 예외가 throw되는 경우 모드로 throw() /std:c++14 선언된 함수에서 예외가 throw되면 결과는 정의되지 않은 동작입니다. 특정 함수가 호출되지 않습니다. 이는 컴파일러가 호출해야 하는 C++14 표준의 차이입니다 std::unexpected . Visual Studio 2017 버전 15.5 이상: 모드에서 /std:c++17 , noexcept noexcept(true) 및 throw() 모두 동일합니다. 모드에서는 /std:c++17 throw() .에 대한 noexcept(true) 별칭입니다. 모드 이상에서는 /std:c++17 이러한 사양 std::terminate 중 하나로 선언된 함수에서 예외가 throw되면 C++17 표준에서 요구하는 대로 호출됩니다. |
noexcept(false) throw(...) 사양 없음 |
함수는 모든 형식의 예외를 throw할 수 있습니다. |
throw(type) |
(C++14 이하) 함수는 형식 type 의 예외를 throw할 수 있습니다. 컴파일러는 구문을 수락하지만 이를 .로 noexcept(false) 해석합니다. 모드 이상에서 /std:c++17 컴파일러는 경고 C5040을 실행합니다. |
애플리케이션에서 예외 처리를 사용하는 경우 호출 스택에는 throw된 예외를 처리하는 함수가 있어야만 표시된 noexcept
noexcept(true)
함수의 외부 범위가 종료됩니다throw()
. 예외를 throw하는 함수와 예외를 처리하는 함수 간에 호출된 noexcept
noexcept(true)
함수가 (또는 throw()
모드에서/std:c++17
) 지정된 경우 noexcept 함수가 예외를 전파할 때 프로그램이 종료됩니다.
함수의 예외 동작은 다음 요인에 따라 달라집니다.
설정된 언어 표준 컴파일 모드 입니다.
C 또는 C++에서 함수를 컴파일하는지 여부
/EH
사용하는 컴파일러 옵션입니다.예외 사양을 명시적으로 지정하는지 여부
C 함수에서는 명시적 예외 사양이 허용되지 않습니다. C 함수는 예외를 throw하지 않는 것으로 간주되며 , /EHa
또는 /EHac
.에서 /EHsc
/EHs
구조적 예외를 throw할 수 있습니다.
다음 표에서는 C++ 함수가 잠재적으로 다양한 컴파일러 예외 처리 옵션에서 throw될 수 있는지 여부를 요약합니다.
함수 | /EHsc |
/EHs |
/EHa |
/EHac |
---|---|---|---|---|
예외 사양이 없는 C++ 함수 | 예 | 네 | 네 | 예 |
또는 noexcept(true) throw() 예외 사양이 있는 noexcept C++ 함수 |
아니요 | 없음 | 네 | 예 |
또는 throw(...) throw(type) 예외 사양이 있는 noexcept(false) C++ 함수 |
예 | 네 | 네 | 예 |
예시
// exception_specification.cpp
// compile with: /EHs
#include <stdio.h>
void handler() {
printf_s("in handler\n");
}
void f1(void) throw(int) {
printf_s("About to throw 1\n");
if (1)
throw 1;
}
void f5(void) throw() {
try {
f1();
}
catch(...) {
handler();
}
}
// invalid, doesn't handle the int exception thrown from f1()
// void f3(void) throw() {
// f1();
// }
void __declspec(nothrow) f2(void) {
try {
f1();
}
catch(int) {
handler();
}
}
// only valid if compiled without /EHc
// /EHc means assume extern "C" functions don't throw exceptions
extern "C" void f4(void);
void f4(void) {
f1();
}
int main() {
f2();
try {
f4();
}
catch(...) {
printf_s("Caught exception from f4\n");
}
f5();
}
About to throw 1
in handler
About to throw 1
Caught exception from f4
About to throw 1
in handler
참고 항목
피드백
https://aka.ms/ContentUserFeedback
출시 예정: 2024년 내내 콘텐츠에 대한 피드백 메커니즘으로 GitHub 문제를 단계적으로 폐지하고 이를 새로운 피드백 시스템으로 바꿀 예정입니다. 자세한 내용은 다음을 참조하세요.다음에 대한 사용자 의견 제출 및 보기