Bagikan melalui


/Zc:implicitNoexcept (Penentu Pengecualian Implisit)

Ketika opsi /Zc:implicitNoexcept ditentukan, pengompilasi menambahkan penentu pengecualian noexcept implisit ke fungsi anggota khusus yang ditentukan kompilator dan ke destruktor dan deallokator yang ditentukan pengguna. Secara default, /Zc:implicitNoexcept diaktifkan agar sesuai dengan standar ISO C++11. Menonaktifkan opsi ini menonaktifkan implisit noexcept pada destruktor dan dealloacator yang ditentukan pengguna dan fungsi anggota khusus yang ditentukan kompilator.

Sintaks

/Zc:implicitNoexcept[-]

Keterangan

/Zc:implicitNoexcept memberi tahu pengompilasi untuk mengikuti bagian 15.4 dari standar ISO C++11. Ini secara implisit menambahkan penentu pengecualian ke setiap fungsi anggota khusus yang dideklarasikan secara implisit noexcept atau eksplisit—konstruktor default, konstruktor salin, konstruktor pemindahan, destruktor, operator penugasan salinan, atau operator penetapan pemindahan—dan setiap fungsi destruktor atau deallocator yang ditentukan pengguna. Deallocator yang ditentukan pengguna memiliki penentu pengecualian implisit noexcept(true) . Untuk destruktor yang ditentukan pengguna, penentu pengecualian implisit adalah noexcept(true) kecuali kelas anggota yang terkandung atau kelas dasar memiliki destruktor yang bukan noexcept(true). Untuk fungsi anggota khusus yang dihasilkan kompilator, jika ada fungsi yang langsung dipanggil oleh fungsi ini secara noexcept(false)efektif , penentu pengecualian implisit adalah noexcept(false). Jika tidak, penentu pengecualian implisit adalah noexcept(true).

Pengkompilasi tidak menghasilkan penentu pengecualian implisit untuk fungsi yang dideklarasikan dengan menggunakan eksplisit noexcept atau throw penentu atau __declspec(nothrow) atribut.

Secara default, /Zc:implicitNoexcept diaktifkan. Opsi /permissive- tidak memengaruhi /Zc:implicitNoexcept.

Jika opsi dinonaktifkan dengan menentukan /Zc:implicitNoexcept-, tidak ada penentu pengecualian implisit yang dihasilkan oleh pengompilasi. Perilaku ini sama dengan Visual Studio 2013, di mana destruktor dan dealokator yang tidak memiliki penentu pengecualian dapat memiliki throw pernyataan. Secara default, dan ketika /Zc:implicitNoexcept ditentukan, jika throw pernyataan ditemui pada waktu proses dalam fungsi dengan penentu implisit noexcept(true) , itu menyebabkan pemanggilan segera , std::terminatedan perilaku penat normal untuk penangan pengecualian tidak dijamin. Untuk membantu mengidentifikasi situasi ini, kompilator menghasilkan Compiler Warning (level 1) C4297. throw Jika disengaja, kami sarankan Anda mengubah deklarasi fungsi Anda agar memiliki penentu eksplisit noexcept(false) alih-alih menggunakan /Zc:implicitNoexcept-.

Sampel ini menunjukkan bagaimana destruktor yang ditentukan pengguna yang tidak memiliki penentu pengecualian eksplisit berperilaku ketika opsi /Zc:implicitNoexcept diatur atau dinonaktifkan. Untuk menampilkan perilaku saat diatur, kompilasi dengan menggunakan cl /EHsc /W4 implicitNoexcept.cpp. Untuk menampilkan perilaku saat dinonaktifkan, kompilasi dengan menggunakan 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;
}

Saat dikompilasi dengan menggunakan pengaturan default /Zc:implicitNoexcept, sampel menghasilkan output ini:

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

Saat dikompilasi dengan menggunakan pengaturan /Zc:implicitNoexcept-, sampel menghasilkan output ini:

~B Exception caught
~D Exception caught
Exit returning EXIT_SUCCESS

Untuk informasi selengkapnya tentang masalah kesuaian di Visual C++, lihat Perilaku Nonstandar.

Untuk mengatur opsi pengkompilasi ini di lingkungan pengembangan Visual Studio

  1. Buka kotak dialog Halaman Properti proyek. Untuk detailnya, lihat Mengatur pengkompilasi C++ dan membuat properti di Visual Studio.

  2. Pilih halaman properti Properti>Konfigurasi C/C++>Baris Perintah.

  3. Ubah properti Opsi Tambahan untuk menyertakan /Zc:implicitNoexcept atau /Zc:implicitNoexcept- lalu pilih OK.

Baca juga

/Zc (Kesuaian)
noexcept
Spesifikasi Pengecualian (throw)
terminate