/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::terminate
a 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
Otevřete dialogové okno Stránky vlastností projektu. Podrobnosti najdete v tématu Nastavení kompilátoru C++ a vlastností sestavení v sadě Visual Studio.
Vyberte stránku vlastností příkazového řádku C/C++>Vlastnosti>konfigurace.
Upravte vlastnost Další možnosti tak, aby zahrnovala /Zc:implicitNoexcept nebo /Zc:implicitNoexcept- a pak zvolte OK.