W C++ istnieje compile-time (stałość na etapie kompilacji) oraz link-time (na etapie łączenia) stałość.
const zmienna — to obiekt, którego nie można zmienić po inicjalizacji. Ale const nie zawsze gwarantuje, że wartość jest znana na etapie kompilacji; może być obliczana tylko w czasie wykonywania.constexpr — gwarantuje, że wyrażenie lub funkcja zostanie obliczona już na etapie kompilacji.Przykład:
const int x = time(0); // const, ale NIE constexpr: wartość obliczana w czasie wykonywania constexpr int y = 2 + 2; // constexpr: znane na etapie kompilacji constexpr int square(int x) { return x * x; } int arr[square(3)]; // rozmiar tablicy — wyrażenie czasu kompilacji
Używaj constexpr dla stałych wyrażeń, które muszą być dostępne dla kompilatora, na przykład dla rozmiarów tablic lub parametrów szablonów.
Czy funkcja zadeklarowana jako constexpr może być wywoływana z nie-stałymi argumentami?
Odpowiedź: Tak! Jeśli argumenty są znane w czasie kompilacji, wynik zostanie obliczony na etapie kompilacji. Jeśli argumenty są znane tylko w czasie wykonywania, funkcja będzie obliczana jak zwykła.
constexpr int double_val(int x) { return x * 2; } int val = std::rand(); int result = double_val(val); // Wywołana podczas wykonywania
Historia
Jeden z modułów ustalał rozmiar tablicy przez
const int, zakładając, że to stała czasu kompilacji. W innym kompilatorze to spowodowało błąd, ponieważ wartość była obliczana w czasie wykonywania, a rozmiar tablicy nie odpowiadał standardowi.
Historia
W obliczeniu haszy kompilator nie mógł zoptymalizować obliczeń, ponieważ używana była zmienna
const, a nieconstexpr. Wynik: spadek wydajności o ponad 2 razy w nowych wersjach.
Historia
Podczas migracji na nowoczesne standardy pomylono słowa kluczowe i zadeklarowano funkcję jako
const, a nieconstexpr, przez co niemożliwe było użycie wyniku w wyrażeniach szablonów czasu kompilacji. Szybka diagnostyka pokazała błąd, ale na przeglądzie trafiła do mastera.