/Zc:implicitNoexcept (niejawne specyfikatory wyjątków)

Po określeniu opcji /Zc:implicitNoexcept kompilator dodaje niejawny specyfikator wyjątku noexcept do funkcji specjalnych zdefiniowanych przez kompilator i destruktorów zdefiniowanych przez użytkownika i destruktorów. Domyślnie opcja /Zc:implicitNoexcept jest włączona w celu zachowania zgodności ze standardem ISO C++11. Wyłączenie tej opcji powoduje wyłączenie niejawnych noexcept destruktorów zdefiniowanych przez użytkownika i destruktorów transakcji oraz specjalnych funkcji składowych zdefiniowanych przez kompilator.

Składnia

/Zc:implicitNoexcept[-]

Uwagi

/Zc:implicitNoexcept nakazuje kompilatorowi wykonanie sekcji 15.4 standardu ISO C++11. Niejawnie dodaje noexcept specyfikator wyjątku do każdej niejawnie zadeklarowanej lub jawnie domyślnej specjalnej funkcji składowej — konstruktora domyślnego, konstruktora kopiowania, konstruktora przenoszenia, konstruktora przenoszenia, destruktora, operatora przypisania kopiowania lub operatora przypisania przenoszenia — i każdej funkcji destruktora zdefiniowanego przez użytkownika lub funkcji cofania przydziału. Przydział zdefiniowany przez użytkownika ma niejawny noexcept(true) specyfikator wyjątku. W przypadku destruktorów zdefiniowanych przez użytkownika specyfikator wyjątku niejawnego jest noexcept(true) , chyba że zawarta klasa składowa lub klasa bazowa ma destruktor, który nie noexcept(true)jest . W przypadku funkcji specjalnych składowych generowanych przez kompilator, jeśli jakakolwiek funkcja wywoływana bezpośrednio przez tę funkcję jest skutecznie noexcept(false), niejawnym specyfikatorem wyjątku jest noexcept(false). W przeciwnym razie specyfikator niejawnego wyjątku to noexcept(true).

Kompilator nie generuje niejawnego specyfikatora wyjątku dla funkcji zadeklarowanych za pomocą jawnych noexcept lub throw specyfikatorów lub atrybutu __declspec(nothrow) .

Domyślnie /Zc:implicitNoexcept jest włączony. / permissive- opcja nie ma wpływu na /Zc:implicitNoexcept.

Jeśli opcja jest wyłączona przez określenie /Zc:implicitNoexcept-, żadne niejawne specyfikatory wyjątków nie są generowane przez kompilator. To zachowanie jest takie samo jak w programie Visual Studio 2013, gdzie destruktory i przydziały, które nie miały specyfikatorów wyjątków, mogą mieć throw instrukcje. Domyślnie i gdy /Zc:implicitNoexcept jest określony, jeśli throw instrukcja napotkana w czasie wykonywania w funkcji z niejawnym noexcept(true) specyfikatorem, powoduje natychmiastowe wywołanie std::terminatemetody i normalne zachowanie odwijania obsługi wyjątków nie jest gwarantowane. Aby ułatwić zidentyfikowanie tej sytuacji, kompilator generuje ostrzeżenie kompilatora (poziom 1) C4297. throw Jeśli obiekt jest zamierzony, zalecamy zmianę deklaracji funkcji na jawny noexcept(false) specyfikator zamiast używania /Zc:implicitNoexcept-.

W tym przykładzie pokazano, jak destruktor zdefiniowany przez użytkownika, który nie ma jawnego specyfikatora wyjątku zachowuje się, gdy opcja /Zc:implicitNoexcept jest ustawiona lub wyłączona. Aby pokazać zachowanie podczas ustawiania, skompiluj przy użyciu polecenia cl /EHsc /W4 implicitNoexcept.cpp. Aby pokazać zachowanie po wyłączeniu, skompiluj przy użyciu polecenia 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;
}

Podczas kompilacji przy użyciu ustawienia domyślnego /Zc:implicitNoexcept przykład generuje następujące dane wyjściowe:

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

Podczas kompilacji przy użyciu ustawienia /Zc:implicitNoexcept-, przykład generuje następujące dane wyjściowe:

~B Exception caught
~D Exception caught
Exit returning EXIT_SUCCESS

Aby uzyskać więcej informacji na temat problemów ze zgodnością w programie Visual C++, zobacz Zachowanie niezgodne.

Aby ustawić tę opcję kompilatora w środowisku programowania Visual Studio

  1. Otwórz okno dialogowe Strony właściwości projektu. Aby uzyskać szczegółowe informacje, zobacz Set C++ compiler and build properties in Visual Studio (Ustawianie właściwości kompilatora języka C++ i kompilowania w programie Visual Studio).

  2. Wybierz stronę Właściwości>konfiguracji C/C++>Wiersza polecenia.

  3. Zmodyfikuj właściwość Opcje dodatkowe, aby uwzględnić /Zc:implicitNoexcept lub /Zc:implicitNoexcept-, a następnie wybierz przycisk OK.

Zobacz też

/Zc (Zgodność)
noexcept
Specyfikacje wyjątków (throw)
Zakończyć