Freigeben über


/Zc:implicitNoexcept (implizite Ausnahmespezifizierer)

Wenn die Option "/Zc:implicitNoexcept " angegeben wird, fügt der Compiler einen impliziten Noexcept-Ausnahmebezeichner zu compilerdefinierten speziellen Memberfunktionen und benutzerdefinierten Destruktoren und Deallocators hinzu. Standardmäßig ist /Zc:implicitNoexcept aktiviert, um dem ISO C++11-Standard zu entsprechen. Durch Deaktivieren dieser Option wird für das implizite noexcept-Element für benutzerdefinierte Destruktoren und Deallokatoren und die speziellen vom Compiler definierten Memberfunktionen deaktiviert.

Syntax

/Zc:implicitNoexcept[-]

Hinweise

/Zc:implicitNoexcept weist den Compiler an, Abschnitt 15.4 des ISO C++11-Standards zu folgen. Er fügt implizit einen noexcept Ausnahmebezeichner zu jeder implizit deklarierten oder explizit standardmäßigen speziellen Memberfunktion hinzu – dem Standardkonstruktor, dem Kopierkonstruktor, dem Konstruktor, dem Destruktor, dem Kopieren des Zuordnungsoperators oder dem Verschieben von Zuordnungsoperatoren und jeder benutzerdefinierten Destruktor- oder Deallocator-Funktion. Ein benutzerdefinierter Deallokator verfügt über einen impliziten noexcept(true)-Ausnahmebezeichner. Für benutzerdefinierte Destruktoren ist noexcept(true) der implizite Ausnahmebezeichner, es sei denn eine enthaltene Elementklasse oder Basisklasse weist einen Destruktor auf, der nicht noexcept(true) ist. Für vom Compiler generierte spezielle Memberfunktionen ist noexcept(false) der implizite Ausnahmebezeichner, wenn eine von dieser Funktion aufgerufene Funktion noexcept(false) ist. Andernfalls ist noexcept(true) der implizite Ausnahmebezeichner.

Für Funktionen, die mit expliziten noexcept- oder throw-Bezeichnern oder einem __declspec(nothrow)-Attribut deklariert wurden, generiert der Compiler keinen impliziten Ausnahmebezeichner.

Standardmäßig ist /Zc:implicitNoexcept aktiviert. Die Option "/permissive" wirkt sich nicht auf /Zc:implicitNoexcept aus.

Wenn die Option durch Angeben von /Zc:implicitNoexcept-deaktiviert wird, werden vom Compiler keine impliziten Ausnahmebezeichner generiert. Dieses Verhalten ist mit dem in Visual Studio 2013 identisch, wo Destruktoren und Deallokatoren ohne Ausnahmebezeichner über throw-Anweisungen verfügen können. Wenn /Zc:implicitNoexcept angegeben wird, wird standardmäßig, wenn eine throw Anweisung zur Laufzeit in einer Funktion mit einem impliziten noexcept(true) Bezeichner gefunden wird, ein sofortiges Aufrufen von std::terminate, und normales Entlastungsverhalten für Ausnahmehandler wird nicht garantiert. Um diese Situation zu identifizieren, generiert der Compiler die Compilerwarnung (Ebene 1) C4297. Wenn dies throw beabsichtigt ist, empfehlen wir, die Funktionsdeklaration so zu ändern, dass sie einen expliziten noexcept(false) Bezeichner anstelle von /Zc:implicitNoexcept-verwendet.

In diesem Beispiel wird gezeigt, wie sich ein benutzerdefinierter Destruktor ohne explizite Ausnahmebezeichner verhält, wenn die Option "/Zc:implicitNoexcept " festgelegt oder deaktiviert wird. Um das Verhalten beim Festlegen anzuzeigen, kompilieren Sie mithilfe cl /EHsc /W4 implicitNoexcept.cppvon . Um das Verhalten beim Deaktivieren anzuzeigen, kompilieren Sie es mithilfe von 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;
}

Beim Kompilieren mithilfe der Standardeinstellung "/Zc:implicitNoexcept" generiert das Beispiel diese Ausgabe:

~B Exception caught
Unexpected throw caused std::terminate
Exit returning EXIT_FAILURE

Bei der Kompilierung mithilfe der Einstellung "/Zc:implicitNoexcept-" generiert das Beispiel diese Ausgabe:

~B Exception caught
~D Exception caught
Exit returning EXIT_SUCCESS

Weitere Informationen über Konformitätsprobleme in Visual C++ finden Sie unter Nonstandard Behavior.

So legen Sie diese Compileroption in der Visual Studio-Entwicklungsumgebung fest

  1. Öffnen Sie das Dialogfeld Eigenschaftenseiten des Projekts. Weitere Informationen erhalten Sie unter Set C++ compiler and build properties in Visual Studio (Festlegen der Compiler- und Buildeigenschaften (C++) in Visual Studio).

  2. Klicken Sie auf der Eigenschaftenseite auf Konfigurationseigenschaften>C/C++>Befehlszeile.

  3. Ändern Sie die Eigenschaft "Zusätzliche Optionen", um "/Zc:implicitNoexcept" oder "/Zc:implicitNoexcept" einzuschließen, und wählen Sie dann "OK" aus.

Siehe auch

/Zc (Übereinstimmung)
noexcept
Ausnahmespezifikationen (throw)
terminate