programowanieC++ Embedded Developer

Opowiedz, jak działa stałość link-time i compile-time w C++. Jaka jest różnica między constexpr a const? Kiedy który z nich używać?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

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.

Pytanie podchwytliwe.

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

Przykłady rzeczywistych błędów wynikających z niewiedzy o niuansach tematu.


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 nie constexpr. 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 nie constexpr, 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.