共用方式為


/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)

編譯器不會為使用明確的 noexceptthrow 規範或 __declspec(nothrow) 屬性所宣告的函式產生隱含的例外狀況規範。

默認會啟用 /Zc:implicitNoexcept/permissive- 選項不會影響 /Zc:implicitNoexcept

如果選項是藉由指定 /Zc:implicitNoexcept-來停用,則編譯程式不會產生隱含例外狀況規範。 這種行為與 Visual Studio 2013 相同,其中沒有例外狀況規範的解構函式和解除配置器可能具有 throw 陳述式。 根據預設,而且指定 /Zc:implicitNoexcept,如果在throw具有隱含noexcept(true)規範的函式中遇到語句,則會導致立即調用 std::terminate,而且不保證例外狀況處理程式的一般回溯行為。 為了協助識別這種情況,編譯程式會產生 編譯程式警告 (層級 1) C4297throw如果 是刻意的,建議您將函式宣告變更為具有明確的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 開發環境中設定這個編譯器選項

  1. 開啟專案的 [屬性頁] 對話方塊。 如需詳細資料,請參閱在 Visual Studio 中設定 C ++ 編譯器和組建屬性

  2. 選取 [組態屬性]>[C/C++]>[命令列] 屬性頁。

  3. 修改 [其他選項] 屬性以包含 /Zc:implicitNoexcept 或 /Zc:implicitNoexcept- ,然後選擇 [確定]。

另請參閱

/Zc (一致性)
noexcept
例外狀況規格 (throw)
terminate