Sdílet prostřednictvím


/Zc:implicitNoexcept (specifikátory implicitních výjimek)

Pokud je zadána možnost /Zc:implicitNoexcept, kompilátor přidá implicitní specifikátor výjimky noexcept ke speciálním členským funkcím definovaným kompilátorem a k uživatelem definovaným destruktorů a uvolnění. Ve výchozím nastavení je /Zc:implicitNoexcept povolen tak, aby odpovídal standardu ISO C++11. Vypnutím této možnosti zakážete implicitní noexcept u uživatelem definovaných destruktorů a dealloacátorů a speciálních členských funkcí definovaných kompilátorem.

Syntaxe

/Zc:implicitNoexcept[-]

Poznámky

/Zc:implicitNoexcept říká kompilátoru, aby postupoval podle oddílu 15.4 standardu ISO C++11. Implicitně přidá noexcept specifikátor výjimky pro každou implicitně deklarovanou nebo explicitně výchozí speciální členovou funkci – výchozí konstruktor, konstruktor kopírování, konstruktor přesunutí, destruktor, operátor přiřazení kopírování nebo operátor přiřazení – a každou uživatelsky definovanou destruktor nebo funkci uvolnění. User-defined deallocator má implicitní noexcept(true) specifikátor výjimky. U destruktorů definovaných uživatelem je noexcept(true) specifikátor implicitní výjimky, pokud neobsahuje obsaženou členskou třídu nebo základní třídu destruktor, který není noexcept(true). Pro speciální členské funkce generované kompilátorem, pokud je jakákoli funkce přímo vyvolána touto funkcí je účinně noexcept(false), specifikátor implicitní výjimky je noexcept(false). Jinak je specifikátor noexcept(true)implicitní výjimky .

Kompilátor negeneruje specifikátor implicitní výjimky pro funkce deklarované pomocí explicitních noexcept nebo throw specifikátorů nebo atributu __declspec(nothrow) .

Ve výchozím nastavení je povolen /Zc:implicitNoexcept . Možnost /permissive- nemá vliv na /Zc:implicitNoexcept.

Pokud je tato možnost zakázána zadáním /Zc:implicitNoexcept-, kompilátor nevygeneruje žádné specifikátory implicitních výjimek. Toto chování je stejné jako v sadě Visual Studio 2013, kde destruktory a uvolněné lokátory, které nemají specifikátory výjimek, mohou mít throw příkazy. Ve výchozím nastavení a když je zadán /Zc:implicitNoexcept , pokud throw je příkaz v době běhu ve funkci s implicitním noexcept(true) specifikátorem, způsobí okamžité vyvolání std::terminatea normální chování odvíjení obslužných rutin výjimek není zaručeno. Kompilátor vygeneruje upozornění kompilátoru (úroveň 1) C4297. Pokud je záměrný throw , doporučujeme změnit deklaraci funkce tak, aby měla explicitní noexcept(false) specifikátor místo použití /Zc:implicitNoexcept-.

Tato ukázka ukazuje, jak se chová destruktor definovaný uživatelem, který nemá žádný explicitní specifikátor výjimky, když je nastavena nebo zakázána možnost /Zc:implicitNoexcept . Chcete-li zobrazit chování při nastavení, zkompilujte pomocí cl /EHsc /W4 implicitNoexcept.cpp. Chcete-li zobrazit chování při zakázání, zkompilujte pomocí .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;
}

Při kompilaci pomocí výchozího nastavení /Zc:implicitNoexcept vygeneruje ukázka tento výstup:

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

Při kompilaci pomocí nastavení /Zc:implicitNoexcept-, ukázka vygeneruje tento výstup:

~B Exception caught
~D Exception caught
Exit returning EXIT_SUCCESS

Další informace o problémech s shodami v jazyce Visual C++ naleznete v tématu Nestandardní chování.

Nastavení tohoto parametru kompilátoru ve vývojovém prostředí Visual Studio

  1. Otevřete dialogové okno Stránky vlastností projektu. Podrobnosti najdete v tématu Nastavení kompilátoru C++ a vlastností sestavení v sadě Visual Studio.

  2. Vyberte stránku vlastností příkazového řádku C/C++>Vlastnosti>konfigurace.

  3. Upravte vlastnost Další možnosti tak, aby zahrnovala /Zc:implicitNoexcept nebo /Zc:implicitNoexcept- a pak zvolte OK.

Viz také

/Zc (shoda)
noexcept
Specifikace výjimek (throw)
Ukončit