/Zc:implicitNoexcept (identificatori di eccezioni implicite)

Quando si specifica l'opzione /Zc:implicitNoexcept, il compilatore aggiunge un identificatore di eccezione noexcept implicito alle funzioni membro speciali definite dal compilatore e ai distruttori e dealloatori definiti dall'utente. Per impostazione predefinita, /Zc:implicitNoexcept è abilitato per la conformità allo standard ISO C++11. La disattivazione di questa opzione disabilita l'eccezione noexcept implicita in distruttori e deallocatori definiti dall'utente e in speciali funzioni membro definite dal compilatore.

Sintassi

/Zc:implicitNoexcept[-]

Osservazioni:

/Zc:implicitNoexcept indica al compilatore di seguire la sezione 15.4 dello standard ISO C++11. Aggiunge in modo implicito un noexcept identificatore di eccezione a ogni funzione membro speciale dichiarata in modo implicito o esplicitamente predefinito, ovvero il costruttore predefinito, il costruttore di copia, il costruttore di spostamento, il distruttore, l'operatore di assegnazione di copia o l'operatore di assegnazione di spostamento e ogni funzione di distruttore o dealloatore definita dall'utente. Un deallocatore definito dall'utente ha un identificatore di eccezione noexcept(true) implicita. Per i distruttori definiti dall'utente, l'identificatore di eccezione implicita è noexcept(true), a meno che una classe di membro contenuta o una classe di base non abbia un distruttore diverso da noexcept(true). Per le speciali funzioni membro generate dal compilatore, se una funzione richiamata direttamente da questa funzione è effettivamente noexcept(false), l'identificatore di eccezione implicita è noexcept(false). In caso contrario, l'identificatore di eccezione implicita è noexcept(true).

Il compilatore non genera un identificatore di eccezione implicita per le funzioni dichiarate usando gli identificatori noexcept o throw espliciti o un attributo __declspec(nothrow).

Per impostazione predefinita, /Zc:implicitNoexcept è abilitato. L'opzione /permissive- non influisce su /Zc:implicitNoexcept.

Se l'opzione è disabilitata specificando /Zc:implicitNoexcept-, nessun identificatore di eccezione implicito viene generato dal compilatore. Questo comportamento è identico in Visual Studio 2013, dove i distruttori e i deallocatori senza identificatori di eccezione possono avere istruzioni throw. Per impostazione predefinita, e quando si specifica /Zc:implicitNoexcept , se viene rilevata un'istruzione throw in fase di esecuzione in una funzione con un identificatore implicito noexcept(true) , causa una chiamata immediata di e il normale comportamento di std::terminaterimozione per i gestori di eccezioni non è garantito. Per identificare questa situazione, il compilatore genera l'avviso del compilatore (livello 1) C4297. Se è throw intenzionale, è consigliabile modificare la dichiarazione di funzione in modo da avere un identificatore esplicito noexcept(false) anziché usare /Zc:implicitNoexcept-.

In questo esempio viene illustrato il comportamento di un distruttore definito dall'utente senza identificatore di eccezione esplicito quando l'opzione /Zc:implicitNoexcept è impostata o disabilitata. Per visualizzare il comportamento quando impostato, compilare usando cl /EHsc /W4 implicitNoexcept.cpp. Per visualizzare il comportamento quando disabilitato, compilare usando 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;
}

Quando viene compilato usando l'impostazione predefinita /Zc:implicitNoexcept, l'esempio genera questo output:

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

Quando viene compilato usando l'impostazione /Zc:implicitNoexcept-, l'esempio genera questo output:

~B Exception caught
~D Exception caught
Exit returning EXIT_SUCCESS

Per altre informazioni sui problemi di conformità in Visual C++, vedere Nonstandard Behavior.

Per impostare l'opzione del compilatore nell'ambiente di sviluppo di Visual Studio

  1. Aprire la finestra di dialogo Pagine delle proprietà del progetto. Per informazioni dettagliate, vedere Impostare il compilatore e le proprietà di compilazione.

  2. Selezionare la pagina delle proprietà Proprietà di configurazione>C/C++>Riga di comando.

  3. Modificare la proprietà Opzioni aggiuntive per includere /Zc:implicitNoexcept o /Zc:implicitNoexcept- e quindi scegliere OK.

Vedi anche

/Zc (conformità)
noexcept
Specifiche di eccezione (generazione)
terminate