Bagikan melalui


constexpr (C++)

Kata kunci constexpr diperkenalkan di C++11 dan ditingkatkan di C++14. Ini berarti constekspresi semut. Seperti const, dapat diterapkan ke variabel: Kesalahan pengkompilasi dimunculkan ketika kode apa pun mencoba memodifikasiifnilai. Tidak seperti const, constexpr juga dapat diterapkan ke fungsi dan ruktor kelas const. constexpr menunjukkan bahwa nilai, atau mengembalikan nilai, adalah constsemut dan, jika memungkinkan, dihitung pada waktu kompilasi.

Nilai constexpr integral dapat digunakan di mana pun const bilangan bulat diperlukan, seperti dalam argumen templat dan deklarasi array. Dan ketika nilai dihitung pada waktu kompilasi alih-alih run time, itu membantu program Anda berjalan lebih cepat dan menggunakan lebih sedikit memori.

Untuk membatasi kompleksitas komputasi semut waktu constkompilasi, dan dampak potensialnya pada waktu kompilasi, standar C++14 mengharuskan jenis dalam constekspresi semut menjadi jenis literal.

Sintaks

constexprjenis harfiah identifier=constant-expression;
constexprident ident tipeliteral{constant-expression};if
constexprident identif jenisliteral(params);
constexprctor(params);

Parameter

params
Satu atau beberapa parameter, yang masing-masing harus merupakan jenis harfiah dan harus menjadi constekspresi semut.

Nilai hasil

Variabel constexpr atau fungsi harus mengembalikan jenis harfiah.

constexpr Variabel

Ferensi utama difantara variabel dan constexpr adalah bahwa inisialisasi const variabel dapat ditangguhkan const hingga run time. Variabel constexpr harus diinisialisasi pada waktu kompilasi. Semua constexpr variabel adalah const.

  • Variabel dapat dideklarasikan dengan constexpr, ketika memiliki jenis harfiah dan diinisialisasi. Jika inisialisasi performed oleh construktor, ruktor constharus dinyatakan sebagai constexpr.

  • Referensi dapat dinyatakan sebagai constexpr ketika kedua kondisi ini terpenuhi: Objek yang direferensikan diinisialisasi oleh constekspresi semut, dan konversi implisit apa pun yang dipanggil selama inisialisasi juga constmerupakan ekspresi semut.

  • Semua deklarasi constexpr variabel atau fungsi harus memiliki constexpr ier spesifikasiif.

constexpr float x = 42.0;
constexpr float y{108};
constexpr float z = exp(5, 3);
constexpr int i; // Error! Not initialized
int j = 0;
constexpr int k = j + 1; //Error! j not a constant expression

Fungsi constexpr

Fungsi constexpr adalah fungsi yang nilai pengembaliannya dapat dihitung pada waktu kompilasi saat menggunakan kode memerlukannya. Menggunakan kode memerlukan nilai pengembalian pada waktu kompilasi untuk menginisialisasi constexpr variabel, atau untuk memberikan argumen templat non-jenis. Saat argumennya adalah constexpr nilai, constexpr fungsi menghasilkan ant waktu constkompilasi. Saat dipanggil dengan non-argumenconstexpr , atau ketika nilainya tidak diperlukan pada waktu kompilasi, nilai tersebut menghasilkan nilai pada waktu proses seperti fungsi reguler. (Perilaku ganda ini menyelamatkan Anda dari keramaian menulis constexpr dan non-versiconstexpr dari fungsi yang sama.)

Fungsi constexpr atau construktor secara inlineimplisit .

Aturan berikut berlaku untuk constexpr fungsi:

  • Fungsi constexpr harus menerima dan mengembalikan hanya jenis harfiah.

  • Fungsi constexpr bisa rekursif.

  • Jadilahfore C++20, constexpr fungsi tidak boleh virtual, dan construktor tidak dapat didefinisikan seperti constexpr ketika kelas penutup memiliki kelas dasar virtual apa pun. Di C++20 dan yang constexpr lebih baru, fungsi bisa virtual. Visual Studio 2019 versi 16.10 dan versi yang lebih baru mendukung constexpr fungsi virtual saat Anda menspesualisasikanify opsi pengkompilasi atau yang /std:c++20 lebih baru.

  • Isi dapat didefinisikan sebagai = default atau = delete.

  • Isi tidak goto boleh berisi pernyataan atau try blok.

  • Spesialisasi eksplisit dari non-templatconstexpr dapat dinyatakan sebagai constexpr:

  • Spesialisasi eksplisit dari constexpr templat tidak juga harus constexpr:

Aturan berikut berlaku untuk constexpr fungsi di Visual Studio 2017 dan yang lebih baru:

  • Ini mungkin berisi if pernyataan dan switch , dan semua pernyataan perulangan termasuk for, berbasis forrentang , while, dan do-while.

  • Ini mungkin berisi deklarasi variabel lokal, tetapi variabel harus diinisialisasi. Ini harus jenis harfiah, dan tidak bisa static atau utas-lokal. Variabel yang dideklarasikan secara lokal tidak diperlukan , constdan dapat bermutasi.

  • Fungsi constexpr non-anggotastatic tidak diperlukan secara implisit const.

constexpr float exp(float x, int n)
{
    return n == 0 ? 1 :
        n % 2 == 0 ? exp(x * x, n / 2) :
        exp(x * x, (n - 1) / 2) * x;
}

Tip

Di debugger Visual Studio, saat men-debug build Debug yang tidak dioptimalkan, Anda dapat mengetahui apakah constexpr fungsi sedang dievaluasi pada waktu kompilasi dengan menempatkan titik henti di dalamnya. Jika titik henti tertembak, fungsi dipanggil pada run-time. Jika tidak, maka fungsi dipanggil pada waktu kompilasi.

ekstern constexpr

Opsi pengkompilasi /Zc:externConstexpr menyebabkan pengkompilasi menerapkan tautan eksternal ke variabel yang dideklarasikan dengan menggunakan extern constexpr. Dalam versi Visual Studio sebelumnya, baik secara default atau ketika /Zc:externConstexpr- adalah ied spesifikasiif, Visual Studio menerapkan tautan internal ke constexpr variabel bahkan ketika extern kata kunci digunakan. Opsi /Zc:externConstexpr tersedia mulai dari Visual Studio 2017 Update 15.6, dan nonaktif secara default. Opsi /permissive- tidak mengaktifkan /Zc:externConstexpr.

Contoh

Contoh berikut menunjukkan constexpr variabel, fungsi, dan jenis yang ditentukan pengguna. Dalam pernyataan terakhir di main(), constexpr fungsi GetValue() anggota adalah panggilan run-time karena nilainya tidak perlu diketahui pada waktu kompilasi.

// constexpr.cpp
// Compile with: cl /EHsc /W4 constexpr.cpp
#include <iostream>

using namespace std;

// Pass by value
constexpr float exp(float x, int n)
{
    return n == 0 ? 1 :
        n % 2 == 0 ? exp(x * x, n / 2) :
        exp(x * x, (n - 1) / 2) * x;
}

// Pass by reference
constexpr float exp2(const float& x, const int& n)
{
    return n == 0 ? 1 :
        n % 2 == 0 ? exp2(x * x, n / 2) :
        exp2(x * x, (n - 1) / 2) * x;
}

// Compile-time computation of array length
template<typename T, int N>
constexpr int length(const T(&)[N])
{
    return N;
}

// Recursive constexpr function
constexpr int fac(int n)
{
    return n == 1 ? 1 : n * fac(n - 1);
}

// User-defined type
class Foo
{
public:
    constexpr explicit Foo(int i) : _i(i) {}
    constexpr int GetValue() const
    {
        return _i;
    }
private:
    int _i;
};

int main()
{
    // foo is const:
    constexpr Foo foo(5);
    // foo = Foo(6); //Error!

    // Compile time:
    constexpr float x = exp(5, 3);
    constexpr float y { exp(2, 5) };
    constexpr int val = foo.GetValue();
    constexpr int f5 = fac(5);
    const int nums[] { 1, 2, 3, 4 };
    const int nums2[length(nums) * 2] { 1, 2, 3, 4, 5, 6, 7, 8 };

    // Run time:
    cout << "The value of foo is " << foo.GetValue() << endl;
}

Persyaratan

Visual Studio 2015 atau versi yang lebih baru.

Baca juga

Deklarasi dan definisi
const