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
constexpr
jenis harfiah identifier=constant-expression;
constexpr
ident ident tipeliteral{constant-expression};if
constexpr
ident identif jenisliteral(params);
constexpr
ctor(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 sebagaiconstexpr
.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 memilikiconstexpr
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 inline
implisit .
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 seperticonstexpr
ketika kelas penutup memiliki kelas dasar virtual apa pun. Di C++20 dan yangconstexpr
lebih baru, fungsi bisa virtual. Visual Studio 2019 versi 16.10 dan versi yang lebih baru mendukungconstexpr
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 atautry
blok.Spesialisasi eksplisit dari non-templat
constexpr
dapat dinyatakan sebagaiconstexpr
:Spesialisasi eksplisit dari
constexpr
templat tidak juga harusconstexpr
:
Aturan berikut berlaku untuk constexpr
fungsi di Visual Studio 2017 dan yang lebih baru:
Ini mungkin berisi
if
pernyataan danswitch
, dan semua pernyataan perulangan termasukfor
, berbasisfor
rentang ,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 ,const
dan dapat bermutasi.Fungsi
constexpr
non-anggotastatic
tidak diperlukan secara implisitconst
.
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
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk