Partager via


/Zc:implicitNoexcept (spécificateurs d'exceptions implicites)

Lorsque l’option /Zc :implicitNoexcept est spécifiée, le compilateur ajoute un spécificateur d’exception noexcept implicite aux fonctions membres spéciales définies par le compilateur et aux destructeurs et aux deallocators définis par l’utilisateur. Par défaut, /Zc :implicitNoexcept est activé pour se conformer à la norme ISO C++11. La désactivation de cette option désactive noexcept implicite sur les annulateurs d'allocation et les destructeurs définis par l'utilisateur et sur les fonctions membres spéciales définies par le compilateur.

Syntaxe

/Zc :implicitNoexcept[-]

Notes

/Zc :implicitNoexcept indique au compilateur de suivre la section 15.4 de la norme ISO C++11. Il ajoute implicitement un spécificateur d’exception noexcept à chaque fonction membre spéciale déclarée implicitement ou explicitement par défaut , le constructeur par défaut, le constructeur de copie, le constructeur de déplacement, le destructeur, l’opérateur d’affectation de copie ou l’opérateur d’affectation de déplacement, et chaque fonction de destructeur ou de deallocator défini par l’utilisateur. Un annulateur d'allocation défini par l'utilisateur possède un spécificateur d'exception noexcept(true) implicite. Pour les destructeurs définis par l'utilisateur, le spécificateur d'exception implicite est noexcept(true) à moins qu'une classe de base ou une classe membre contenue possède un destructeur qui n'est pas noexcept(true). Pour les fonctions membres spéciales générées par le compilateur, si une fonction quelconque directement appelée par cette fonction est effectivement noexcept(false), le spécificateur d'exception implicite est noexcept(false). Sinon, le spécificateur d'exception implicite est noexcept(true).

Le compilateur ne génère pas un spécificateur d'exception implicite pour les fonctions déclarées à l'aide de spécificateurs noexcept ou throw explicites ou d'un attribut __declspec(nothrow).

Par défaut, /Zc :implicitNoexcept est activé. L’option /permissive- n’affecte pas /Zc :implicitNoexcept.

Si l’option est désactivée en spécifiant /Zc :implicitNoexcept-, aucun spécificateur d’exception implicite n’est généré par le compilateur. Ce comportement est identique à celui de Visual Studio 2013, où les destructeurs et les annulateurs d'allocation qui n'avaient pas de spécificateur d'exception pouvaient avoir des instructions throw. Par défaut, et quand /Zc :implicitNoexcept est spécifié, si une throw instruction est rencontrée au moment de l’exécution dans une fonction avec un spécificateur implicite noexcept(true) , elle provoque un appel immédiat de , et le comportement normal de std::terminatedéroulement pour les gestionnaires d’exceptions n’est pas garanti. Pour identifier cette situation, le compilateur génère l’avertissement du compilateur (niveau 1) C4297. Si la throw valeur est intentionnelle, nous vous recommandons de modifier votre déclaration de fonction pour qu’elle ait un spécificateur explicite noexcept(false) au lieu d’utiliser /Zc :implicitNoexcept-.

Cet exemple montre comment un destructeur défini par l’utilisateur qui n’a aucun spécificateur d’exception explicite se comporte lorsque l’option /Zc :implicitNoexcept est définie ou désactivée. Pour afficher le comportement lors de la définition, compilez à l’aide cl /EHsc /W4 implicitNoexcept.cppde . Pour afficher le comportement lorsqu’il est désactivé, compilez à l’aide cl /EHsc /W4 /Zc:implicitNoexcept- implicitNoexcept.cppde .

// 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;
}

Lors de la compilation à l’aide du paramètre par défaut /Zc :implicitNoexcept, l’exemple génère cette sortie :

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

Lors de la compilation à l’aide du paramètre /Zc :implicitNoexcept-, l’exemple génère cette sortie :

~B Exception caught
~D Exception caught
Exit returning EXIT_SUCCESS

Pour plus d’informations sur les problèmes de conformité dans Visual C++, consultez Nonstandard Behavior.

Pour définir cette option du compilateur dans l'environnement de développement Visual Studio

  1. Ouvrez la boîte de dialogue Pages de propriété du projet. Pour plus d’informations, consultez Définir le compilateur C++ et les propriétés de build dans Visual Studio.

  2. Sélectionnez la page de propriétés Propriétés de configuration>C/C++>Ligne de commande.

  3. Modifiez la propriété Options supplémentaires pour inclure /Zc :implicitNoexcept ou /Zc :implicitNoexcept, puis choisissez OK.

Voir aussi

/Zc (Conformité)
noexcept
Spécifications d’exception (throw)
terminate