/Zc:implicitNoexcept (隱含的例外狀況規範)
指定 /Zc:implicitNoexcept 選項時,編譯程式會將隱含 noexcept 例外狀況規範新增至編譯程式定義的特殊成員函式,以及使用者定義的解構函式和解除分配器。 默認會 啟用 /Zc:implicitNoexcept ,以符合 ISO C++11 標準。 關閉此選項會在使用者定義的解構函式和解除配置器,以及編譯器定義的特殊成員函式上停用隱含的 noexcept
。
語法
/Zc:implicitNoexcept[-]
備註
/Zc:implicitNoexcept 會指示編譯程式遵循 ISO C++11 標準的第 15.4 節。 它會隱含地將例外狀況規範新增 noexcept
至每個隱含宣告或明確預設的特殊成員函式,也就是預設建構函式、複製建構函式、移動建構函式、解構函式、複製指派運算符或移動指派運算符,以及每個使用者定義解構函式或解除分配子函式。 使用者定義的解除配置器具有隱含的 noexcept(true)
例外狀況規範。 若為使用者定義的解構函式,隱含的例外狀況規範為 noexcept(true)
,除非內含的成員類別或基底類別具有不是 noexcept(true)
的解構函式。 若為編譯器產生的特殊成員函式,如果此函式直接叫用的任何函式實際上就是 noexcept(false)
,則隱含的例外狀況規範為 noexcept(false)
。 否則,隱含的例外狀況規範為 noexcept(true)
。
編譯器不會為使用明確的 noexcept
或 throw
規範或 __declspec(nothrow)
屬性所宣告的函式產生隱含的例外狀況規範。
默認會啟用 /Zc:implicitNoexcept。 /permissive- 選項不會影響 /Zc:implicitNoexcept。
如果選項是藉由指定 /Zc:implicitNoexcept-來停用,則編譯程式不會產生隱含例外狀況規範。 這種行為與 Visual Studio 2013 相同,其中沒有例外狀況規範的解構函式和解除配置器可能具有 throw
陳述式。 根據預設,而且指定 /Zc:implicitNoexcept 時,如果在throw
具有隱含noexcept(true)
規範的函式中遇到語句,則會導致立即調用 std::terminate
,而且不保證例外狀況處理程式的一般回溯行為。 為了協助識別這種情況,編譯程式會產生 編譯程式警告 (層級 1) C4297。 throw
如果 是刻意的,建議您將函式宣告變更為具有明確的noexcept(false)
規範,而不是使用 /Zc:implicitNoexcept-。
此範例示範當使用者定義解構函式在設定或停用 /Zc:implicitNoexcept 選項時,沒有明確例外狀況規範的行為。 若要在設定時顯示行為,請使用 cl /EHsc /W4 implicitNoexcept.cpp
編譯。 若要在停用時顯示行為,請使用 cl /EHsc /W4 /Zc:implicitNoexcept- implicitNoexcept.cpp
編譯。
// implicitNoexcept.cpp
// Compile by using: cl /EHsc /W4 implicitNoexcept.cpp
// Compile by using: cl /EHsc /W4 /Zc:implicitNoexcept- implicitNoexcept.cpp
#include <iostream>
#include <cstdlib> // for std::exit, EXIT_FAILURE, EXIT_SUCCESS
#include <exception> // for std::set_terminate
void my_terminate()
{
std::cout << "Unexpected throw caused std::terminate" << std::endl;
std::cout << "Exit returning EXIT_FAILURE" << std::endl;
std::exit(EXIT_FAILURE);
}
struct A {
// Explicit noexcept overrides implicit exception specification
~A() noexcept(false) {
throw 1;
}
};
struct B : public A {
// Compiler-generated ~B() definition inherits noexcept(false)
~B() = default;
};
struct C {
// By default, the compiler generates an implicit noexcept(true)
// specifier for this user-defined destructor. To enable it to
// throw an exception, use an explicit noexcept(false) specifier,
// or compile by using /Zc:implicitNoexcept-
~C() {
throw 1; // C4297, calls std::terminate() at run time
}
};
struct D : public C {
// This destructor gets the implicit specifier of its base.
~D() = default;
};
int main()
{
std::set_terminate(my_terminate);
try
{
{
B b;
}
}
catch (...)
{
// exception should reach here in all cases
std::cout << "~B Exception caught" << std::endl;
}
try
{
{
D d;
}
}
catch (...)
{
// exception should not reach here if /Zc:implicitNoexcept
std::cout << "~D Exception caught" << std::endl;
}
std::cout << "Exit returning EXIT_SUCCESS" << std::endl;
return EXIT_SUCCESS;
}
使用預設設定 /Zc:implicitNoexcept 編譯時,此範例會產生下列輸出:
~B Exception caught
Unexpected throw caused std::terminate
Exit returning EXIT_FAILURE
使用 /Zc:implicitNoexcept-設定編譯時,此範例會產生下列輸出:
~B Exception caught
~D Exception caught
Exit returning EXIT_SUCCESS
如需 Visual C++ 中一致性問題的詳細資訊,請參閱 Nonstandard Behavior。
在 Visual Studio 開發環境中設定這個編譯器選項
開啟專案的 [屬性頁] 對話方塊。 如需詳細資料,請參閱在 Visual Studio 中設定 C ++ 編譯器和組建屬性。
選取 [組態屬性]>[C/C++]>[命令列] 屬性頁。
修改 [其他選項] 屬性以包含 /Zc:implicitNoexcept 或 /Zc:implicitNoexcept- ,然後選擇 [確定]。