ПрограммированиеC++ Embedded разработчик

Расскажите, как работает link-time и compile-time константность в C++. В чём разница между constexpr и const? Когда какой из них использовать?

Проходите собеседования с ИИ помощником Hintsage

Ответ.

В C++ существует compile-time (константность на этапе компиляции) и link-time (на этапе компоновки) константность.

  • const переменная — это объект, который нельзя изменить после инициализации. Но const не всегда гарантирует, что значение известно на этапе компиляции; оно может быть вычислено только во время выполнения.
  • constexpr — гарантирует, что выражение или функция будет вычислено уже на этапе компиляции.

Пример:

const int x = time(0); // const, но НЕ constexpr: значение вычисляется во времени выполнения constexpr int y = 2 + 2; // constexpr: известно на этапе компиляции constexpr int square(int x) { return x * x; } int arr[square(3)]; // размер массива — выражение времени компиляции

Используйте constexpr для константных выражений, которые должны быть доступны компилятору, например, для размерами массива или шаблонных параметров.

Вопрос с подвохом.

Может ли функция, объявленная как constexpr, вызываться с не-константными аргументами?

Ответ: Да! Если аргументы известны во время компиляции, результат будет вычислен на этапе компиляции. Если аргументы известны только во время выполнения, функция будет вычисляться как обычная.

constexpr int double_val(int x) { return x * 2; } int val = std::rand(); int result = double_val(val); // Вызовится на этапе run-time

Примеры реальных ошибок из-за незнания тонкостей темы.


История

Один из модулей задавал размер массива через const int, рассчитывая, что это константа времени компиляции. На другом компиляторе это вызвало ошибку, потому что значение было вычислено на run-time, и размер массива не соответствовал стандарту.


История

В расчёте хешей компилятор не мог оптимизировать вычисления, потому что использовалась const переменная, а не constexpr. Итог: снижение производительности более чем в 2 раза на новых релизах.


История

При миграции на современные стандарты перепутали ключевые слова и объявили функцию как const, а не constexpr, из-за чего нельзя было использовать результат в compile-time выражениях шаблонов. Быстрая диагностика показала ошибку, но на ревью она ушла в master.